根据issue #499下的 open 现已关闭devextreme-reactive github repo,我希望能够在Grid
/下进行某种复合过滤TableView
个组件。
目前,有两个过滤组件,分别具有以下示例:
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>
);
}
}
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' },
]
答案 0 :(得分:1)
在查看过滤代码库后,快速回答是否 它不是直接的,但它是可能的。
更新: 该库的一位开发人员已确认有一种方法可以过滤行。附加到本答案结尾的示例。
正如我在<{3}}下的 open 现已关闭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 团队实施一种运行复合列过滤的官方方式。
在我们等待的时候,前一个例子应该启动并运行许多用例。
该库的一位开发人员非常友好地提供了(devextreme-reactive github repo)一个实现基于行的自定义过滤器的方法的示例和演示:
首先,使用单个过滤器编辑器创建自定义过滤器行。接下来,使用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
开发on the original issue:
取决于过滤器数量,而不是列数。每个过滤器都将应用于每一行。