- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一条路线/customers,其中 List 客户 正在呈现。在同一条路线上还有一个 side drawer展示。那个抽屉包含一个带有 Filter 的列表帮助主题。
当我开始在侧抽屉的过滤器中输入时,url 发生了变化。这是根据 react-admin 的列表过滤器的工作方式。
问题是客户列表注意到路线变化。实际上,它会根据与帮助主题 相关的搜索词开始查询和重新加载客户。当然没有找到客户。
我希望客户列表不会注意到我正在过滤帮助主题。我的目标解决方案是当我输入帮助主题搜索词时,侧抽屉中的列表过滤器不会更改 url。
我如何配置或自定义侧边抽屉中的过滤器以在键入时不更改 url,而是将当前过滤器值存储在组件状态之类的东西中?
实际上,由于过滤器以一种形式存在(通过 react-final-form),它保持自己的状态,所以我可以接受这样的解决方案。但是当然 publishToUrl
不是 Filter 的可用属性。
const MyFilter = props => (
<Filter {...props} publishToUrl={false} >
<TextInput source="title" />
</Filter>
);
相关:
最佳答案
下面的代码会移除 List 组件与 Redux Store 和 Location 的关联,它可以用来在一个页面上显示多个列表
使用这个列表而不是 react 管理员的列表
创建自己的列表组件
import * as React from 'react';
import PropTypes from 'prop-types';
import {
} from 'ra-core';
import {ListView} from 'ra-ui-materialui';
import {useListController} from '../../controller/useListController';
export const TitlePropType = PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
]);
/**
* List page component
*
* The <List> component renders the list layout (title, buttons, filters, pagination),
* and fetches the list of records from the REST API.
* It then delegates the rendering of the list of records to its child component.
* Usually, it's a <Datagrid>, responsible for displaying a table with one row for each post.
*
* In Redux terms, <List> is a connected component, and <Datagrid> is a dumb component.
*
* The <List> component accepts the following props:
*
* - actions
* - aside
* - component
* - filter (the permanent filter to apply to the query)
* - filters (a React component used to display the filter form)
* - pagination
* - perPage
* - sort
* - title
*
* @example
*
* const PostFilter = (props) => (
* <Filter {...props}>
* <TextInput label="Search" source="q" alwaysOn />
* <TextInput label="Title" source="title" />
* </Filter>
* );
* export const PostList = (props) => (
* <List {...props}
* title="List of posts"
* sort={{ field: 'published_at' }}
* filter={{ is_published: true }}
* filters={PostFilter}
* >
* <Datagrid>
* <TextField source="id" />
* <TextField source="title" />
* <EditButton />
* </Datagrid>
* </List>
* );
*/
export const List = props => {
return <ListView {...props} {...useListController(props)} />;
}
List.propTypes = {
// the props you can change
actions: PropTypes.element,
aside: PropTypes.element,
bulkActionButtons: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]),
children: PropTypes.node,
classes: PropTypes.object,
className: PropTypes.string,
filter: PropTypes.object,
filterDefaultValues: PropTypes.object,
filters: PropTypes.element,
pagination: PropTypes.element,
perPage: PropTypes.number.isRequired,
sort: PropTypes.shape({
field: PropTypes.string,
order: PropTypes.string,
}),
title: TitlePropType,
// the props managed by react-admin
authProvider: PropTypes.func,
hasCreate: PropTypes.bool.isRequired,
hasEdit: PropTypes.bool.isRequired,
hasList: PropTypes.bool.isRequired,
hasShow: PropTypes.bool.isRequired,
location: PropTypes.object,
match: PropTypes.object,
path: PropTypes.string,
resource: PropTypes.string.isRequired,
};
List.defaultProps = {
filter: {},
perPage: 10,
};
Controller /useListController
import { isValidElement, ReactElement, useEffect, useMemo } from 'react';
import inflection from 'inflection';
import { useSelector } from 'react-redux';
import get from 'lodash/get';
import {useCheckMinimumRequiredProps, useTranslate,
useNotify, useGetList, CRUD_GET_LIST, useVersion, useRecordSelection } from 'react-admin';
import { ListParams } from 'ra-core';
import { Sort, RecordMap, Identifier, ReduxState, Record } from 'ra-core';
import {SORT_ASC} from 'ra-core/esm/reducer/admin/resource/list/queryReducer';
import useListParams from './useListParams';
export interface ListProps {
// the props you can change
filter?: object;
filters?: ReactElement<any>;
filterDefaultValues?: object;
pagination?: ReactElement<any>;
perPage?: number;
sort?: Sort;
// the props managed by react-admin
basePath: string;
debounce?: number;
hasCreate?: boolean;
hasEdit?: boolean;
hasList?: boolean;
hasShow?: boolean;
path?: string;
query: ListParams;
resource: string;
[key: string]: any;
}
const defaultSort = {
field: 'id',
order: SORT_ASC,
};
const defaultData = {};
export interface ListControllerProps<RecordType = Record> {
basePath: string;
currentSort: Sort;
data: RecordMap<RecordType>;
defaultTitle: string;
displayedFilters: any;
filterValues: any;
hasCreate: boolean;
hideFilter: (filterName: string) => void;
ids: Identifier[];
loading: boolean;
loaded: boolean;
onSelect: (ids: Identifier[]) => void;
onToggleItem: (id: Identifier) => void;
onUnselectItems: () => void;
page: number;
perPage: number;
resource: string;
selectedIds: Identifier[];
setFilters: (filters: any, displayedFilters: any) => void;
setPage: (page: number) => void;
setPerPage: (page: number) => void;
setSort: (sort: string) => void;
showFilter: (filterName: string, defaultValue: any) => void;
total: number;
version: number;
}
/**
* Prepare data for the List view
*
* @param {Object} props The props passed to the List component.
*
* @return {Object} controllerProps Fetched and computed data for the List view
*
* @example
*
* import { useListController } from 'react-admin';
* import ListView from './ListView';
*
* const MyList = props => {
* const controllerProps = useListController(props);
* return <ListView {...controllerProps} {...props} />;
* }
*/
export const useListController = <RecordType = Record>(
props: ListProps
): ListControllerProps<RecordType> => {
useCheckMinimumRequiredProps('List', ['basePath', 'resource'], props);
const {
basePath,
resource,
hasCreate,
filterDefaultValues,
sort = defaultSort,
perPage = 10,
filter,
debounce = 500,
} = props;
if (filter && isValidElement(filter)) {
throw new Error(
'<List> received a React element as `filter` props. If you intended to set the list filter elements, use the `filters` (with an s) prop instead. The `filter` prop is internal and should not be set by the developer.'
);
}
const translate = useTranslate();
const notify = useNotify();
const version = useVersion();
const [query, queryModifiers] = useListParams({
resource,
filterDefaultValues,
sort,
perPage,
debounce
});
const [selectedIds, selectionModifiers] = useRecordSelection(resource);
/**
* We want the list of ids to be always available for optimistic rendering,
* and therefore we need a custom action (CRUD_GET_LIST) that will be used.
*/
const { ids, total, loading, loaded } = useGetList<RecordType>(
resource,
{
page: query.page,
perPage: query.perPage,
},
{ field: query.sort, order: query.order },
{ ...query.filter, ...filter },
{
action: CRUD_GET_LIST,
onFailure: error =>
notify(
typeof error === 'string'
? error
: error.message || 'ra.notification.http_error',
'warning'
),
}
);
const data = useSelector(
(state: ReduxState): RecordMap<RecordType> =>
get(
state.admin.resources,
[resource, 'data'],
defaultData
) as RecordMap<RecordType>
);
// When the user changes the page/sort/filter, this controller runs the
// useGetList hook again. While the result of this new call is loading,
// the ids and total are empty. To avoid rendering an empty list at that
// moment, we override the ids and total with the latest loaded ones.
const defaultIds = [];
const defaultTotal = 0;
useEffect(() => {
if (
query.page <= 0 ||
(!loading && query.page > 1 && (ids || []).length === 0)
) {
// query for a page that doesn't exist, set page to 1
queryModifiers.setPage(1);
}
}, [loading, query.page, ids, queryModifiers]);
const currentSort = useMemo(
() => ({
field: query.sort,
order: query.order,
}),
[query.sort, query.order]
);
const resourceName = translate(`resources.${resource}.name`, {
smart_count: 2,
_: inflection.humanize(inflection.pluralize(resource)),
});
const defaultTitle = translate('ra.page.list', {
name: resourceName,
});
return {
basePath,
currentSort,
data,
defaultTitle,
displayedFilters: query.displayedFilters,
filterValues: query.filterValues,
hasCreate,
hideFilter: queryModifiers.hideFilter,
ids: typeof total === 'undefined' ? defaultIds : ids,
loaded: loaded || defaultIds.length > 0,
loading,
onSelect: selectionModifiers.select,
onToggleItem: selectionModifiers.toggle,
onUnselectItems: selectionModifiers.clearSelection,
page: query.page,
perPage: query.perPage,
resource,
selectedIds,
setFilters: queryModifiers.setFilters,
setPage: queryModifiers.setPage,
setPerPage: queryModifiers.setPerPage,
setSort: queryModifiers.setSort,
showFilter: queryModifiers.showFilter,
total: typeof total === 'undefined' ? defaultTotal : total,
version,
};
};
export const injectedProps = [
'basePath',
'currentSort',
'data',
'defaultTitle',
'displayedFilters',
'filterValues',
'hasCreate',
'hideFilter',
'ids',
'loading',
'loaded',
'onSelect',
'onToggleItem',
'onUnselectItems',
'page',
'perPage',
'refresh',
'resource',
'selectedIds',
'setFilters',
'setPage',
'setPerPage',
'setSort',
'showFilter',
'total',
'version',
];
export default useListController;
Controller /useListParams
import {useCallback, useMemo, useState} from 'react';
import lodashDebounce from 'lodash/debounce';
import set from 'lodash/set';
import { ListParams } from 'ra-core';
import { Sort, removeKey, removeEmpty } from 'ra-core';
import queryReducer from 'ra-core/esm/reducer/admin/resource/list/queryReducer';
import {SORT_ASC, SET_SORT, SET_PAGE, SET_PER_PAGE, SET_FILTER} from 'ra-core/esm/reducer/admin/resource/list/queryReducer';
interface ListParamsOptions {
resource: string;
perPage?: number;
sort?: Sort;
filterDefaultValues?: object;
debounce?: number;
}
interface Parameters extends ListParams {
filterValues: object;
displayedFilters: {
[key: string]: boolean;
};
requestSignature: any[];
}
interface Modifiers {
changeParams: (action: any) => void;
setPage: (page: number) => void;
setPerPage: (pageSize: number) => void;
setSort: (sort: string) => void;
setFilters: (filters: any, displayedFilters: any) => void;
hideFilter: (filterName: string) => void;
showFilter: (filterName: string, defaultValue: any) => void;
}
const emptyObject = {};
const defaultSort = {
field: 'id',
order: SORT_ASC,
};
const defaultParams = {};
/**
* Get the list parameters (page, sort, filters) and modifiers.
*
* These parameters are merged from 3 sources:
* - the query string from the URL
* - the params stored in the state (from previous navigation)
* - the options passed to the hook (including the filter defaultValues)
*
* @returns {Array} A tuple [parameters, modifiers].
* Destructure as [
* { page, perPage, sort, order, filter, filterValues, displayedFilters, requestSignature },
* { setFilters, hideFilter, showFilter, setPage, setPerPage, setSort }
* ]
*
* @example
*
* const [listParams, listParamsActions] = useListParams({
* resource: 'posts',
* location: location // From react-router. Injected to your component by react-admin inside a List
* filterDefaultValues: {
* published: true
* },
* sort: {
* field: 'published_at',
* order: 'DESC'
* },
* perPage: 25
* });
*
* const {
* page,
* perPage,
* sort,
* order,
* filter,
* filterValues,
* displayedFilters,
* requestSignature
* } = listParams;
*
* const {
* setFilters,
* hideFilter,
* showFilter,
* setPage,
* setPerPage,
* setSort,
* } = listParamsActions;
*/
const useListParams = ({
resource,
filterDefaultValues,
sort = defaultSort,
perPage = 10,
debounce = 500,
}: ListParamsOptions): [Parameters, Modifiers] => {
const [params, setParams] = useState(defaultParams);
const requestSignature = [
resource,
params,
filterDefaultValues,
JSON.stringify(sort),
perPage
];
const query = useMemo(
() =>
getQuery({
params,
filterDefaultValues,
sort,
perPage
}),
requestSignature // eslint-disable-line react-hooks/exhaustive-deps
);
const changeParams = useCallback(action => {
const newParams = queryReducer(query, action);
setParams(newParams);
}, requestSignature); // eslint-disable-line react-hooks/exhaustive-deps
const setSort = useCallback(
(newSort: string) =>
changeParams({ type: SET_SORT, payload: { sort: newSort } }),
requestSignature // eslint-disable-line react-hooks/exhaustive-deps
);
const setPage = useCallback(
(newPage: number) => changeParams({ type: SET_PAGE, payload: newPage }),
requestSignature // eslint-disable-line react-hooks/exhaustive-deps
);
const setPerPage = useCallback(
(newPerPage: number) =>
changeParams({ type: SET_PER_PAGE, payload: newPerPage }),
requestSignature // eslint-disable-line react-hooks/exhaustive-deps
);
const filterValues = query.filter || emptyObject;
const displayedFilterValues = query.displayedFilters || emptyObject;
const debouncedSetFilters = lodashDebounce(
(newFilters, newDisplayedFilters) => {
let payload = {
filter: removeEmpty(newFilters),
displayedFilters: undefined,
};
if (newDisplayedFilters) {
payload.displayedFilters = Object.keys(
newDisplayedFilters
).reduce((filters, filter) => {
return newDisplayedFilters[filter]
? { ...filters, [filter]: true }
: filters;
}, {});
}
changeParams({
type: SET_FILTER,
payload,
});
},
debounce
);
const setFilters = useCallback(
(filters, displayedFilters) =>
debouncedSetFilters(filters, displayedFilters),
requestSignature // eslint-disable-line react-hooks/exhaustive-deps
);
const hideFilter = useCallback((filterName: string) => {
const newFilters = removeKey(filterValues, filterName);
const newDisplayedFilters = {
...displayedFilterValues,
[filterName]: undefined,
};
setFilters(newFilters, newDisplayedFilters);
}, requestSignature); // eslint-disable-line react-hooks/exhaustive-deps
const showFilter = useCallback((filterName: string, defaultValue: any) => {
const newFilters = set(filterValues, filterName, defaultValue);
const newDisplayedFilters = {
...displayedFilterValues,
[filterName]: true,
};
setFilters(newFilters, newDisplayedFilters);
}, requestSignature); // eslint-disable-line react-hooks/exhaustive-deps
return [
{
displayedFilters: displayedFilterValues,
filterValues,
requestSignature,
...query,
},
{
changeParams,
setPage,
setPerPage,
setSort,
setFilters,
hideFilter,
showFilter,
},
];
};
/**
* Check if user has already set custom sort, page, or filters for this list
*
* User params come from the Redux store as the params props. By default,
* this object is:
*
* { filter: {}, order: null, page: 1, perPage: null, sort: null }
*
* To check if the user has custom params, we must compare the params
* to these initial values.
*
* @param {Object} params
*/
export const hasCustomParams = (params: ListParams) => {
return (
params &&
params.filter &&
(Object.keys(params.filter).length > 0 ||
params.order != null ||
params.page !== 1 ||
params.perPage != null ||
params.sort != null)
);
};
/**
* Merge list params from 3 different sources:
* - the query string
* - the params stored in the state (from previous navigation)
* - the props passed to the List component (including the filter defaultValues)
*/
export const getQuery = ({
filterDefaultValues,
params,
sort,
perPage,
}) => {
const query: Partial<ListParams> =
hasCustomParams(params)
? { ...params } : { filter: filterDefaultValues || {} };
if (!query.sort) {
query.sort = sort.field;
query.order = sort.order;
}
if (!query.perPage) {
query.perPage = perPage;
}
if (!query.page) {
query.page = 1;
}
return {
...query,
page: getNumberOrDefault(query.page, 1),
perPage: getNumberOrDefault(query.perPage, 10),
} as ListParams;
};
export const getNumberOrDefault = (
possibleNumber: string | number | undefined,
defaultValue: number
) =>
(typeof possibleNumber === 'string'
? parseInt(possibleNumber, 10)
: possibleNumber) || defaultValue;
export default useListParams;
关于url - 如何不使用 react-admin 更改列表过滤的 url?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59883643/
SO亲爱的 friend 们: 2014 年 3 月 18 日。我正在处理一种情况,在使用 ng-repeat 时,数组内的元素(我从 Json 字符串中获取)更改了原始顺序。 需要明确的是,数组中的
有很多问题询问如何在 JavaScript 单击处理程序中更改 div 的类,例如,此处:Change Div style onclick .我理解得很好(只需更改 .className),并且它有效
我从access导入了一个数据库到mysql,但其中一个表的列名“股数”带有空格,但我尝试更改、替换甚至删除列名,但失败了。任何人都可以帮助解决这一问题 String UpdateQuary = "U
我正在做一个随机的学校元素。 目前,我有一个包含两个 CSS 的页面。一种用于正常 View ,一种用于残障人士 View 。 此页面还包括两个按钮,它们将更改使用的样式表。 function c
我需要使用 javascript 更改 HTML 元素中的文本,但我不知道该怎么做。 ¿有什么帮助吗? 我把它定义成这样: Text I want to change. 我正在尝试这样做: docum
我在它自己的文件 nav_bar.shtml 中有一个主导航栏,每个其他页面都包含该导航栏。这个菜单栏是一个 jQuery 菜单栏(ApyCom 是销售这些导航栏的公司的名称)。导航栏上的元素如何确定
我正在摆弄我的代码,并开始想知道这个变化是否来自: if(array[index] == 0) 对此: if(!array[index] != 0) 可能会影响任何代码,或者它只是做同样的事情而我不需
我一直在想办法调整控制台窗口的大小。这是我正在使用的函数的代码: #include #include #define WIDTH 70 #define HEIGHT 35 HANDLE wHnd;
我有很多情况会导致相同的消息框警报。 有没有比做几个 if 语句更简单/更好的解决方案? PRODUCTS BOX1 BOX2 BOX3
我有一个包含这些元素的 XELEMENT B Bob Petier 19310227 1 我想像这样转换前缀。 B Bob Pet
我使用 MySQL 5.6 遇到了这种情况: 此查询有效并返回预期结果: select * from some_table where a = 'b' and metadata->>"$.countr
我想知道是否有人知道可以检测 R 中日期列格式的任何中断的包或函数,即检测日期向量格式更改的位置,例如: 11/2/90 12/2/90 . . . 15/Feb/1990 16/Feb/1990 .
我希望能够在小部件显示后更改 GtkButton 的标签 char *ButtonStance == "Connect"; GtkWidget *EntryButton = gtk_button_ne
我正在使用 Altera DE2 FPGA 开发板并尝试使用 SD 卡端口和音频线路输出。我正在使用 VHDL 和 C 进行编程,但由于缺乏经验/知识,我在 C 部分遇到了困难。 目前,我可以从 SD
注意到这个链接后: http://www.newscientist.com/blogs/nstv/2010/12/best-videos-of-2010-progress-bar-illusion.h
我想知道在某些情况下,即使剧本任务已成功执行并且 ok=2,ansible 也会显示“changed=0”。使用 Rest API 和 uri 模块时会发生这种情况。我试图找到解释但没有成功。谁能告诉
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicate: add buttons to push notification alert 是否可以在远程通知显示的警报框中指定有
当您的 TabBarController 中有超过 5 个 View Controller 时,系统会自动为您设置一个“更多” View 。是否可以更改此 View 中导航栏的颜色以匹配我正在使用的颜
如何更改.AndroidStudioBeta文件夹的位置,默认情况下,该文件夹位于Windows中的\ .. \ User \ .AndroidStudioBeta,而不会破坏任何内容? /编辑: 找
我目前正在尝试将更具功能性的编程风格应用于涉及低级(基于 LWJGL)GUI 开发的项目。显然,在这种情况下,需要携带很多状态,这在当前版本中是可变的。我的目标是最终拥有一个完全不可变的状态,以避免状
我是一名优秀的程序员,十分优秀!