如何使用具有 FilteringState 和/或 LocalFiltering 的 DevExtreme React 网格表进行 OR 过滤?
Posted
技术标签:
【中文标题】如何使用具有 FilteringState 和/或 LocalFiltering 的 DevExtreme React 网格表进行 OR 过滤?【英文标题】:How to do OR filter using DevExtreme React Grid Table with either FilteringState and/or LocalFiltering? 【发布时间】:2018-05-05 23:41:11 【问题描述】:根据 open 现在在devextreme-reactive github repo 下关闭issue #499,我希望能够在Grid
/TableView
组件下进行某种复合过滤。
目前有两个过滤组件,分别举例如下:
FilteringState
import React from 'react';
import
FilteringState,
LocalFiltering,
from '@devexpress/dx-react-grid';
import
Grid,
TableView,
TableHeaderRow,
TableFilterRow,
from '@devexpress/dx-react-grid-material-ui';
import
generateRows,
from '../../demo-data/generator';
export default class Demo extends React.PureComponent
constructor(props)
super(props);
this.state =
columns: [
name: 'name', title: 'Name' ,
name: 'sex', title: 'Sex' ,
name: 'city', title: 'City' ,
name: 'car', title: 'Car' ,
],
rows: generateRows( length: 14 ),
filters: [ columnName: 'car', value: 'cruze' ],
;
this.changeFilters = filters => this.setState( filters );
render()
const rows, columns = this.state;
return (
<Grid
rows=rows
columns=columns
>
<FilteringState
filters=this.state.filters
onFiltersChange=this.changeFilters
/>
<LocalFiltering />
<TableView />
<TableHeaderRow />
<TableFilterRow />
</Grid>
);
LocalFiltering
import React from 'react';
import
FilteringState,
LocalFiltering,
from '@devexpress/dx-react-grid';
import
Grid,
TableView,
TableHeaderRow,
TableFilterRow,
from '@devexpress/dx-react-grid-material-ui';
import
generateRows,
from '../../demo-data/generator';
const toLowerCase = value => String(value).toLowerCase();
const filterByCity = (value, filter) => toLowerCase(value).startsWith(toLowerCase(filter.value));
const getColumnPredicate = columnName => (columnName === 'city' ? filterByCity : undefined);
export default class Demo extends React.PureComponent
constructor(props)
super(props);
this.state =
columns: [
name: 'name', title: 'Name' ,
name: 'sex', title: 'Sex' ,
name: 'city', title: 'City' ,
name: 'car', title: 'Car' ,
],
rows: generateRows( length: 14 ),
;
render()
const rows, columns = this.state;
return (
<Grid
rows=rows
columns=columns
>
<FilteringState defaultFilters=[ columnName: 'city', value: 'Paris' ] />
<LocalFiltering getColumnPredicate=getColumnPredicate />
<TableView />
<TableHeaderRow />
<TableFilterRow />
</Grid>
);
这两个示例都受到以下事实的限制:一次只能将一个过滤器应用于指定的每一列。
换句话说,即使我可以创建多个过滤器,但每个过滤器一次只能应用于一列。
例如,假设我有数据:
[
name: 'jane',
lastName: 'doe',
,
name: 'davey',
lastName: 'jones',
,
name: 'walter',
lastName: 'white',
,
]
如果我实现单个SearchBox
组件,onChange()
会将以下过滤器发送到底层FilteringState
:
[
columnName: 'name', value: 'd' ,
columnName: 'lastName', value: 'd' ,
]
然后我会得到No data
,因为过滤器被应用为 AND 而不是 OR。
有没有办法实现一个触发器来启用/禁用过滤器被视为OR?
或者,有没有办法以这种方式发送过滤器?:
[
columnNames: ['name', 'lastName'], value: 'd' ,
]
【问题讨论】:
【参考方案1】:查看过滤代码库后,快速回答是否这不是直截了当,但有可能。
更新: 该库的一位开发人员已确认有一种过滤行的方法。示例附加到此答案的末尾。
正如我在 open 中提到的,现在在 devextreme-reactive github repo 下关闭了 issue #499,我目前的解决方法是在发送之前预过滤行数据Grid
组件。
根据问题中提供的name
/ lastName
示例,我建议类似于以下内容:
import React, Component from 'react';
import TextField from 'material-ui/TextField';
import
SortingState,
LocalSorting,
from '@devexpress/dx-react-grid';
import PropTypes from 'prop-types';
import
Grid, TableView, TableHeaderRow
from '@devexpress/dx-react-grid-material-ui';
export default class MySearchableTableView extends Component
filterBySearch = ev =>
const data = this.props;
const searchValue = ev.target.value;
const filteredData = data.filter(
row => (toLowerCase(row.name).startsWith(toLowerCase(searchValue)) || toLowerCase(row.lastName).startsWith(toLowerCase(searchValue)))
);
this.setState(data: filteredData);
;
updateStateFromProps = (props) =>
this.setState(data: Object.assign(, props.data));
;
componentDidMount()
this.updateStateFromProps(this.props);
componentWillReceiveProps(nextProps)
this.updateStateFromProps(nextProps);
render()
const data = this.state;
const columns = this.props;
return [
<TextField
key="text-field-component"
label="Search"
fullWidth
onChange=this.filterBySearch
/>,
<Grid
key="grid-component"
rows=data || []
columns=columns || []
>
<TableView />
<TableHeaderRow />
<TableFilterRow />
</Grid>,
];
希望在不久的将来,DevExpress 团队实现了一种运行复合列过滤的官方方式。
与此同时,在我们等待的同时,前面的示例应该会启动并运行许多用例。
更新
该库的一位开发人员非常友好地提供了 (on the original issue) 一个示例和演示,说明了一种实现基于行的自定义过滤器的方法:
首先,使用单个过滤器编辑器创建一个自定义过滤器行。接下来,使用 onChange 事件处理程序创建自定义过滤器:
<TableFilterRow
filterRowTemplate=() => (<TableRow>
<TableCell>
<Input
onChange=(e) =>
this.setState( filters: [
columnName: 'custom',
value: e.target.value
]);
/>
</TableCell>
</TableRow>
)
/>
然后,在列谓词中使用此过滤器:
<LocalFiltering
getColumnPredicate=() => (value, filter, row) => (
row.firstFieldName.indexOf(filter.value) > -1
||
row.secondFieldName.indexOf(filter.value) > -1
)
/>
乍一看,这会导致行过滤器运行多次,因为它在getColumnPredicate
下的每行列运行。
再说一遍,devextreme-reactive
devs have confirmed:
这取决于过滤器计数,而不是列数。每个过滤器将应用于每一行。
【讨论】:
以上是关于如何使用具有 FilteringState 和/或 LocalFiltering 的 DevExtreme React 网格表进行 OR 过滤?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过使用 dplyr 或其他包在 R 中具有最小值和最大值的查询来实现组?
如何使用 jquery 或 javascript 计算具有特定值的行数?
如何使用 Swift 将具有两个不同键的两个值存储到数组或字典中? [关闭]