Skip to content

Commit 14ff4c5

Browse files
committed
feat(Table): add onConditionChange & doNotHandleConditionChange
1 parent 71dc9e0 commit 14ff4c5

File tree

6 files changed

+5527
-1285
lines changed

6 files changed

+5527
-1285
lines changed

src/components/Table/Table.jsx

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ class Table extends Component {
184184
cell: PropTypes.any
185185
})
186186
}),
187+
/**
188+
* 表格的筛选等条件变更时的回调
189+
* @param condition - 变更的数据
190+
* @param condition.order - 排序
191+
* @param condition.filter - 筛选
192+
* @param condition.searchValue - 搜索
193+
*/
194+
onConditionChange: PropTypes.func,
195+
/**
196+
* order、filter、searchValue、pagination变化时表格内部不处理
197+
*/
198+
doNotHandleCondition: PropTypes.bool,
187199
/**
188200
* 右键菜单
189201
* @param record - 该行的记录值
@@ -269,11 +281,30 @@ class Table extends Component {
269281
handleSearch = v => {
270282
if (v !== this.state.searchValue) {
271283
this.setState({
272-
searchValue: v,
273284
pagination: { ...this.state.pagination, current: 1 }
274285
});
286+
this.handleConditionChange({ searchValue: v });
275287
}
276288
};
289+
handleConditionChange = condition => {
290+
this.setState({
291+
...condition
292+
});
293+
const { onConditionChange } = this.props;
294+
condition = {
295+
..._.pick(this.state, ['order', 'filters', 'searchValue']),
296+
...condition
297+
};
298+
299+
let { order, filters, searchValue } = condition;
300+
301+
onConditionChange &&
302+
onConditionChange({
303+
order: order ? _.pick(order, ['key', 'state']) : null,
304+
filters: _.map(filters, (filter, key) => ({ key, value: filter.value })),
305+
searchValue
306+
});
307+
};
277308
renderFilter = (filter, key, dataIndex) => {
278309
if (!filter) {
279310
return null;
@@ -331,15 +362,12 @@ class Table extends Component {
331362
filters[key] = filter;
332363
}
333364
this.setState({
334-
filters: filters,
335365
pagination: { ...this.state.pagination, current: 1 }
336366
});
367+
this.handleConditionChange({ filters });
337368
};
338369
clearFilter = () => {
339-
this.setState({
340-
filters: {},
341-
searchValue: ''
342-
});
370+
this.handleConditionChange({ filters: {}, searchValue: '' });
343371
};
344372
renderOrder = (order, key, dataIndex, state = 'none') => {
345373
if (!order) {
@@ -366,7 +394,7 @@ class Table extends Component {
366394
);
367395
};
368396
handleOrder = (key, { dataIndex, handleOrder, state }) => {
369-
this.setState({
397+
this.handleConditionChange({
370398
order:
371399
state === 'asc'
372400
? null
@@ -409,7 +437,7 @@ class Table extends Component {
409437
return result;
410438
};
411439
getDataSource = () => {
412-
const { dataSource, handleSearch } = this.props;
440+
const { dataSource, handleSearch, doNotHandleCondition } = this.props;
413441
const { filters, order, searchValue } = this.state;
414442
let data = _.clone(dataSource);
415443
const doFilter = (dataSource, filter) => {
@@ -442,15 +470,15 @@ class Table extends Component {
442470
return handleFilter(record[dataIndex], record, value, multiple);
443471
});
444472
};
445-
if (!_.isEmpty(filters)) {
473+
if (!doNotHandleCondition && !_.isEmpty(filters)) {
446474
_.forEach(filters, (filter, key) => (data = doFilter(data, filter, key)));
447475
}
448476
const doSearch = (dataSource, searchValue) => {
449477
return dataSource.filter(record => {
450478
return handleSearch(record, searchValue);
451479
});
452480
};
453-
if (searchValue && searchValue.trim()) {
481+
if (!doNotHandleCondition && searchValue && searchValue.trim()) {
454482
data = doSearch(data, searchValue.trim());
455483
}
456484
const doOrder = (dataSource, order) => {
@@ -464,13 +492,13 @@ class Table extends Component {
464492
}[state]
465493
);
466494
};
467-
if (order) {
495+
if (!doNotHandleCondition && order) {
468496
data = doOrder(data, order);
469497
}
470498

471499
const total = data.length;
472500
const pagination = this.getPagination();
473-
if (pagination !== null) {
501+
if (!doNotHandleCondition && pagination !== null) {
474502
const { current, pageSize } = pagination;
475503
const from = (current - 1) * pageSize;
476504
const to = from + pageSize;
@@ -744,7 +772,10 @@ class Table extends Component {
744772
/* eslint-enable no-unused-vars */
745773
const pagination = this.getPagination();
746774
const { filters = {}, searchValue, columnConfig } = this.state;
747-
const { dataSource, total } = this.getDataSource();
775+
let { dataSource, total } = this.getDataSource();
776+
if (pagination && 'total' in pagination) {
777+
total = pagination.total;
778+
}
748779
const columns = this.getColumns(dataSource);
749780
const defaultExpandAllRowsProps = !defaultExpandAllRows
750781
? null

src/components/Table/Table.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,22 @@
121121
```js {"codepath": "subTable.jsx"}
122122
```
123123

124+
* onConditionChange - 由于 pagination 的某些设计,onConditionChange 返回值中不包含 pagination 变化,要监听 pagination 请使用 pagination 参数
125+
126+
```js {"codepath": "onConditionChange.jsx"}
127+
```
128+
129+
* doNotHandleCondition
130+
131+
```js {"codepath": "doNotHandleCondition.jsx"}
132+
```
133+
124134
* 远程加载数据
125135

126136
```js {"codepath": "loadingDataFromRemote.jsx"}
127137
```
138+
139+
* 后端分页、搜索、筛选、排序
140+
141+
```js {"codepath": "fullRemoteTable.jsx"}
142+
```
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React from 'react';
2+
3+
import Table from 'src/components/Table';
4+
5+
// demo start
6+
class Demo extends React.Component {
7+
render() {
8+
let data = [];
9+
data.length = 33;
10+
data.fill({});
11+
data = data.map((d, i) => ({
12+
key: i,
13+
name: `name-${i}`,
14+
desc: `desc-${i}`
15+
}));
16+
const columns = [
17+
{
18+
title: 'name',
19+
dataIndex: 'name',
20+
key: 'name',
21+
width: 100,
22+
filter: {
23+
options: [1, 2, 3, 4]
24+
},
25+
order: true
26+
},
27+
{
28+
title: 'desc',
29+
dataIndex: 'desc',
30+
key: 'desc',
31+
width: 200,
32+
filter: {
33+
options: [1, 2, 3, 4],
34+
multiple: true
35+
},
36+
order: true
37+
},
38+
{
39+
title: 'Operations',
40+
dataIndex: '',
41+
key: 'operation',
42+
render: (text, record) => (
43+
<a onClick={e => this.handleRemove(record.key, e)} href="#">
44+
Remove
45+
</a>
46+
)
47+
}
48+
];
49+
return (
50+
<div>
51+
<div className="demo-wrap">
52+
<Table
53+
onConditionChange={console.log}
54+
doNotHandleCondition
55+
title={() => {
56+
return (
57+
<div className="clear-fixed">
58+
<div style={{ float: 'right' }}>
59+
<Table.SearchInput style={{ marginRight: 8 }} />
60+
</div>
61+
</div>
62+
);
63+
}}
64+
dataSource={data}
65+
columns={columns}
66+
/>
67+
</div>
68+
</div>
69+
);
70+
}
71+
}
72+
// demo end
73+
74+
export default Demo;
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import React from 'react';
2+
import _ from 'lodash';
3+
4+
import Table from 'src/components/Table';
5+
import Loading from 'src/components/Loading';
6+
7+
// demo start
8+
class Demo extends React.Component {
9+
constructor(props) {
10+
super(props);
11+
this.state = {
12+
dataSource: [],
13+
pagination: {
14+
total: 0,
15+
current: 1,
16+
pageSize: 10,
17+
onChange: (...args) => this.handlePaginationChange(...args),
18+
onPageSizeChange: (...args) => this.handlePaginationChange(...args)
19+
}
20+
};
21+
}
22+
componentDidMount() {
23+
this.fetch();
24+
}
25+
26+
fetch() {
27+
const {
28+
order,
29+
filters,
30+
searchValue,
31+
pagination: { current, pageSize }
32+
} = this.state;
33+
34+
const params = {
35+
Order: order,
36+
Filters: _.map(filters, filter => {
37+
return {
38+
Key: filter.key,
39+
Option: filter.value
40+
};
41+
}),
42+
Search: searchValue,
43+
Current: current,
44+
Limit: pageSize
45+
};
46+
console.log('params: ', params);
47+
this.setState({
48+
loading: true
49+
});
50+
return new Promise(resolve => {
51+
const data = new Array(pageSize).fill(null).map((v, i) => {
52+
const index = i + (current - 1) * pageSize;
53+
return {
54+
index,
55+
name: `name - ${index}`,
56+
describe: `describe - ${index}`,
57+
random: (Math.random() * 1000) | 0
58+
};
59+
});
60+
setTimeout(() => {
61+
resolve({
62+
dataSource: data,
63+
total: 1001
64+
});
65+
}, 1000);
66+
}).then(result => {
67+
this.setState({
68+
loading: false,
69+
dataSource: result.dataSource,
70+
pagination: {
71+
...this.state.pagination,
72+
total: result.total
73+
}
74+
});
75+
});
76+
}
77+
handlePaginationChange(current, pageSize) {
78+
this.setState(
79+
{
80+
pagination: { ...this.state.pagination, current, pageSize }
81+
},
82+
() => {
83+
this.fetch();
84+
}
85+
);
86+
}
87+
handleConditionChange(condition) {
88+
this.setState(
89+
{
90+
...condition
91+
},
92+
() => {
93+
this.fetch();
94+
}
95+
);
96+
}
97+
render() {
98+
const { dataSource, pagination, loading } = this.state;
99+
100+
const columns = [
101+
{
102+
title: 'name',
103+
dataIndex: 'name',
104+
key: 'name',
105+
width: 100,
106+
filter: {
107+
options: [1, 2, 3, 4]
108+
},
109+
order: true
110+
},
111+
{
112+
title: 'describe',
113+
dataIndex: 'describe',
114+
key: 'describe',
115+
width: 200,
116+
filter: {
117+
options: [1, 2, 3, 4],
118+
multiple: true
119+
},
120+
order: true
121+
},
122+
{
123+
title: 'random',
124+
key: 'random',
125+
dataIndex: 'random'
126+
}
127+
];
128+
return (
129+
<div>
130+
<div className="demo-wrap">
131+
<Loading loading={loading} tip="Loading ...">
132+
<Table
133+
title={() => {
134+
return (
135+
<div className="clear-fixed">
136+
<div style={{ float: 'right' }}>
137+
<Table.SearchInput style={{ marginRight: 8 }} />
138+
</div>
139+
</div>
140+
);
141+
}}
142+
pagination={pagination}
143+
rowKey="index"
144+
dataSource={dataSource}
145+
scroll={{ y: 600 }}
146+
columns={columns}
147+
onConditionChange={condition => {
148+
console.log(condition);
149+
this.handleConditionChange(condition);
150+
}}
151+
doNotHandleCondition
152+
/>
153+
</Loading>
154+
</div>
155+
</div>
156+
);
157+
}
158+
}
159+
// demo end
160+
161+
export default Demo;

0 commit comments

Comments
 (0)