controlled filters

This commit is contained in:
afc163 2016-03-29 16:35:06 +08:00
parent 0dbc69ea8e
commit 137d57da08
2 changed files with 75 additions and 23 deletions

View File

@ -4,6 +4,10 @@
使用受控属性对筛选和排序状态进行控制。
> 1. columns 中定义了 fileredValue 和 sortOrder 属性即视为受控模式。
> 2. 只支持同时对一列进行排序,请保证只有一列的 sortOrder 属性是生效的。
---
````jsx
@ -34,33 +38,41 @@ const data = [{
const App = React.createClass({
getInitialState() {
return {
filteredValue: {},
sortedValue: {},
filteredInfo: null,
sortedInfo: null,
};
},
handleChange(pagination, filters, sorter) {
console.log('各类参数是', pagination, filters, sorter);
this.setState({
filteredValue: filters,
sortedValue: sorter,
filteredInfo: filters,
sortedInfo: sorter,
});
},
clearFilters(e) {
e.preventDefault();
this.setState({ filteredValue: {} });
this.setState({ filteredInfo: null });
},
clearAll(e) {
e.preventDefault();
this.setState({
filteredInfo: null,
sortedInfo: null,
});
},
setAgeSort(e) {
e.preventDefault();
this.setState({
sortedValue: {
sortedInfo: {
order: 'descend',
columnKey: 'age',
},
});
},
render() {
const { sortedValue, filteredValue } = this.state;
sortedValue.column = sortedValue.column || {};
let { sortedInfo, filteredInfo } = this.state;
sortedInfo = sortedInfo || {};
filteredInfo = filteredInfo || {};
const columns = [{
title: '姓名',
dataIndex: 'name',
@ -69,16 +81,16 @@ const App = React.createClass({
{ text: '姓李的', value: '李' },
{ text: '姓胡的', value: '胡' },
],
filteredValue: filteredValue.name,
filteredValue: filteredInfo.name,
onFilter: (value, record) => record.name.indexOf(value) === 0,
sorter: (a, b) => a.name.length - b.name.length,
sortOrder: sortedValue.columnKey === 'name' && sortedValue.order,
sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
}, {
title: '年龄',
dataIndex: 'age',
key: 'age',
sorter: (a, b) => a.age - b.age,
sortOrder: sortedValue.columnKey === 'age' && sortedValue.order,
sortOrder: sortedInfo.columnKey === 'age' && sortedInfo.order,
}, {
title: '地址',
dataIndex: 'address',
@ -87,16 +99,17 @@ const App = React.createClass({
{ text: '南湖', value: '南湖' },
{ text: '西湖', value: '西湖' },
],
filteredValue: filteredValue.address,
filteredValue: filteredInfo.address,
onFilter: (value, record) => record.address.indexOf(value) === 0,
sorter: (a, b) => a.address.length - b.address.length,
sortOrder: sortedValue.columnKey === 'address' && sortedValue.order,
sortOrder: sortedInfo.columnKey === 'address' && sortedInfo.order,
}];
return (
<div>
<div className="table-operations">
<a href="#" onClick={this.clearFilters}>清除筛选</a>
<a href="#" onClick={this.setAgeSort}>年龄降序排序</a>
<a href="#" onClick={this.clearFilters}>清除筛选</a>
<a href="#" onClick={this.clearAll}>清除筛选和排序</a>
</div>
<Table columns={columns} dataSource={data} onChange={this.handleChange} />
</div>

View File

@ -31,7 +31,7 @@ const Table = React.createClass({
return {
//
selectedRowKeys: this.props.selectedRowKeys || [],
filters: {},
filters: this.getFiltersFromColumns(),
selectionDirty: false,
...this.getSortStateFromColumns(),
radioIndex: null,
@ -113,14 +113,19 @@ const Table = React.createClass({
selectedRowKeys: nextProps.rowSelection.selectedRowKeys || [],
});
}
if ('columns' in nextProps) {
if (this.hasSortOrderInColumns(nextProps.columns)) {
const sortState = this.getSortStateFromColumns(nextProps.columns);
if (sortState && (
sortState.sortColumn !== this.state.sortColumn ||
sortState.sortOrder !== this.state.sortOrder)) {
if (sortState.sortColumn !== this.state.sortColumn ||
sortState.sortOrder !== this.state.sortOrder) {
this.setState(sortState);
}
}
if (this.hasFilteredValueInColumns(nextProps.columns)) {
const filters = this.getFiltersFromColumns(nextProps.columns);
if (this.isFiltersChanged(filters)) {
this.setState({ filters });
}
}
},
setSelectedRowKeys(selectedRowKeys) {
@ -141,6 +146,38 @@ const Table = React.createClass({
return this.props.pagination !== false;
},
isFiltersChanged(filters) {
let filtersChanged = false;
if (Object.keys(filters).length !== Object.keys(this.state.filters).length) {
filtersChanged = true;
} else {
Object.keys(filters).forEach(columnKey => {
if (filters[columnKey] !== this.state.filters[columnKey]) {
filtersChanged = true;
}
});
}
return filtersChanged;
},
hasSortOrderInColumns(columns) {
return (columns || this.props.columns).some(column => 'sortOrder' in column);
},
hasFilteredValueInColumns(columns) {
return (columns || this.props.columns).some(column => 'filteredValue' in column);
},
getFiltersFromColumns(columns) {
let filters = {};
(columns || this.props.columns).forEach(col => {
if (col.filteredValue) {
filters[this.getColumnKey(col)] = col.filteredValue;
}
});
return filters;
},
getSortedColumn(columns) {
return (columns || this.props.columns).filter(col => col.sortOrder)[0];
},
@ -194,7 +231,7 @@ const Table = React.createClass({
sortColumn,
};
// Controlled
if (!this.getSortStateFromColumns()) {
if (!this.hasSortOrderInColumns()) {
this.setState(newState);
}
this.props.onChange(...this.prepareParamsArguments({ ...this.state, ...newState }));
@ -203,7 +240,7 @@ const Table = React.createClass({
handleFilter(column, nextFilters) {
const filters = {
...this.state.filters,
[this.getColumnKey(column)]: nextFilters
[this.getColumnKey(column)]: nextFilters,
};
// Remove filters not in current columns
const currentColumnKeys = this.props.columns.map(c => this.getColumnKey(c));
@ -216,8 +253,10 @@ const Table = React.createClass({
selectionDirty: false,
filters,
};
this.setState(newState);
this.setSelectedRowKeys([]);
// Controlled
if (!this.hasFilteredValueInColumns()) {
this.setState(newState);
}
this.props.onChange(...this.prepareParamsArguments({ ...this.state, ...newState }));
},