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 ````jsx
@ -34,33 +38,41 @@ const data = [{
const App = React.createClass({ const App = React.createClass({
getInitialState() { getInitialState() {
return { return {
filteredValue: {}, filteredInfo: null,
sortedValue: {}, sortedInfo: null,
}; };
}, },
handleChange(pagination, filters, sorter) { handleChange(pagination, filters, sorter) {
console.log('各类参数是', pagination, filters, sorter); console.log('各类参数是', pagination, filters, sorter);
this.setState({ this.setState({
filteredValue: filters, filteredInfo: filters,
sortedValue: sorter, sortedInfo: sorter,
}); });
}, },
clearFilters(e) { clearFilters(e) {
e.preventDefault(); e.preventDefault();
this.setState({ filteredValue: {} }); this.setState({ filteredInfo: null });
},
clearAll(e) {
e.preventDefault();
this.setState({
filteredInfo: null,
sortedInfo: null,
});
}, },
setAgeSort(e) { setAgeSort(e) {
e.preventDefault(); e.preventDefault();
this.setState({ this.setState({
sortedValue: { sortedInfo: {
order: 'descend', order: 'descend',
columnKey: 'age', columnKey: 'age',
}, },
}); });
}, },
render() { render() {
const { sortedValue, filteredValue } = this.state; let { sortedInfo, filteredInfo } = this.state;
sortedValue.column = sortedValue.column || {}; sortedInfo = sortedInfo || {};
filteredInfo = filteredInfo || {};
const columns = [{ const columns = [{
title: '姓名', title: '姓名',
dataIndex: 'name', dataIndex: 'name',
@ -69,16 +81,16 @@ const App = React.createClass({
{ text: '姓李的', value: '李' }, { text: '姓李的', value: '李' },
{ text: '姓胡的', value: '胡' }, { text: '姓胡的', value: '胡' },
], ],
filteredValue: filteredValue.name, filteredValue: filteredInfo.name,
onFilter: (value, record) => record.name.indexOf(value) === 0, onFilter: (value, record) => record.name.indexOf(value) === 0,
sorter: (a, b) => a.name.length - b.name.length, sorter: (a, b) => a.name.length - b.name.length,
sortOrder: sortedValue.columnKey === 'name' && sortedValue.order, sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
}, { }, {
title: '年龄', title: '年龄',
dataIndex: 'age', dataIndex: 'age',
key: 'age', key: 'age',
sorter: (a, b) => a.age - b.age, sorter: (a, b) => a.age - b.age,
sortOrder: sortedValue.columnKey === 'age' && sortedValue.order, sortOrder: sortedInfo.columnKey === 'age' && sortedInfo.order,
}, { }, {
title: '地址', title: '地址',
dataIndex: 'address', dataIndex: 'address',
@ -87,16 +99,17 @@ const App = React.createClass({
{ text: '南湖', value: '南湖' }, { text: '南湖', value: '南湖' },
{ text: '西湖', value: '西湖' }, { text: '西湖', value: '西湖' },
], ],
filteredValue: filteredValue.address, filteredValue: filteredInfo.address,
onFilter: (value, record) => record.address.indexOf(value) === 0, onFilter: (value, record) => record.address.indexOf(value) === 0,
sorter: (a, b) => a.address.length - b.address.length, sorter: (a, b) => a.address.length - b.address.length,
sortOrder: sortedValue.columnKey === 'address' && sortedValue.order, sortOrder: sortedInfo.columnKey === 'address' && sortedInfo.order,
}]; }];
return ( return (
<div> <div>
<div className="table-operations"> <div className="table-operations">
<a href="#" onClick={this.clearFilters}>清除筛选</a>
<a href="#" onClick={this.setAgeSort}>年龄降序排序</a> <a href="#" onClick={this.setAgeSort}>年龄降序排序</a>
<a href="#" onClick={this.clearFilters}>清除筛选</a>
<a href="#" onClick={this.clearAll}>清除筛选和排序</a>
</div> </div>
<Table columns={columns} dataSource={data} onChange={this.handleChange} /> <Table columns={columns} dataSource={data} onChange={this.handleChange} />
</div> </div>

View File

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