Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fcf7800

Browse files
fix #152
implement remote sorting
2 parents bdfc4eb + 01337f5 commit fcf7800

File tree

9 files changed

+279
-35
lines changed

9 files changed

+279
-35
lines changed

‎docs/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,17 @@ There's only two arguments will be passed to `onTableChange`: `type` and `newSta
249249

250250
* `filter`
251251
* `pagination`
252+
* `sort`
252253

253254
Following is a shape of `newState`
254255

255256
```js
256257
{
257258
page, // newest page
258-
sizePerPage, //newest sizePerPage
259-
filters // an object which have current filter status per column
259+
sizePerPage, // newest sizePerPage
260+
sortField, // newest sort field
261+
sortOrder, // newest sort order
262+
filters, // an object which have current filter status per column
263+
data // when you enable remote sort, you may need to base on data to sort if data is filtered/searched
260264
}
261265
```
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* eslint no-restricted-syntax: 0 */
2+
import React from 'react';
3+
import PropTypes from 'prop-types';
4+
import BootstrapTable from 'react-bootstrap-table2';
5+
import Code from 'components/common/code-block';
6+
import { productsGenerator } from 'utils/common';
7+
8+
const products = productsGenerator(5);
9+
10+
const columns = [{
11+
dataField: 'id',
12+
text: 'Product ID'
13+
}, {
14+
dataField: 'name',
15+
text: 'Product Name',
16+
sort: true
17+
}, {
18+
dataField: 'price',
19+
text: 'Product Price',
20+
sort: true
21+
}];
22+
23+
const sourceCode = `\
24+
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
25+
26+
const columns = [{
27+
dataField: 'id',
28+
text: 'Product ID',
29+
}, {
30+
dataField: 'name',
31+
text: 'Product Name',
32+
filter: textFilter()
33+
}, {
34+
dataField: 'price',
35+
text: 'Product Price',
36+
filter: textFilter()
37+
}];
38+
39+
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
40+
`;
41+
42+
const RemoteSort = props => (
43+
<div>
44+
<BootstrapTable
45+
remote={ { sort: true } }
46+
keyField="id"
47+
data={ props.data }
48+
columns={ columns }
49+
onTableChange={ props.onTableChange }
50+
/>
51+
<Code>{ sourceCode }</Code>
52+
</div>
53+
);
54+
55+
RemoteSort.propTypes = {
56+
data: PropTypes.array.isRequired,
57+
onTableChange: PropTypes.func.isRequired
58+
};
59+
60+
class Container extends React.Component {
61+
constructor(props) {
62+
super(props);
63+
this.state = {
64+
data: products
65+
};
66+
}
67+
68+
handleTableChange = (type, { sortField, sortOrder, data }) => {
69+
setTimeout(() => {
70+
let result;
71+
if (sortOrder === 'asc') {
72+
result = data.sort((a, b) => {
73+
if (a[sortField] > b[sortField]) {
74+
return 1;
75+
} else if (b[sortField] > a[sortField]) {
76+
return -1;
77+
}
78+
return 0;
79+
});
80+
} else {
81+
result = data.sort((a, b) => {
82+
if (a[sortField] > b[sortField]) {
83+
return -1;
84+
} else if (b[sortField] > a[sortField]) {
85+
return 1;
86+
}
87+
return 0;
88+
});
89+
}
90+
this.setState(() => ({
91+
data: result
92+
}));
93+
}, 2000);
94+
}
95+
96+
render() {
97+
return (
98+
<RemoteSort
99+
data={ this.state.data }
100+
onTableChange={ this.handleTableChange }
101+
/>
102+
);
103+
}
104+
}
105+
106+
export default Container;

‎packages/react-bootstrap-table2-example/stories/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
8888
import TableOverlay from 'examples/loading-overlay/table-overlay';
8989

9090
// remote
91+
import RemoteSort from 'examples/remote/remote-sort';
9192
import RemoteFilter from 'examples/remote/remote-filter';
9293
import RemotePaginationTable from 'examples/remote/remote-pagination';
9394
import RemoteAll from 'examples/remote/remote-all';
@@ -190,6 +191,7 @@ storiesOf('EmptyTableOverlay', module)
190191
.add('Table Overlay', () => <TableOverlay />);
191192

192193
storiesOf('Remote', module)
194+
.add('Remote Sort', () => <RemoteSort />)
193195
.add('Remote Filter', () => <RemoteFilter />)
194196
.add('Remote Pagination', () => <RemotePaginationTable />)
195197
.add('Remote All', () => <RemoteAll />);

‎packages/react-bootstrap-table2/src/props-resolver/remote-resolver.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export default ExtendBase =>
88
page: store.page,
99
sizePerPage: store.sizePerPage,
1010
filters: store.filters,
11+
sortField: store.sortField,
12+
sortOrder: store.sortOrder,
13+
data: store.data,
1114
...state
1215
};
1316
}
@@ -22,6 +25,11 @@ export default ExtendBase =>
2225
return remote === true || (_.isObject(remote) && remote.filter);
2326
}
2427

28+
isRemoteSort() {
29+
const { remote } = this.props;
30+
return remote === true || (_.isObject(remote) && remote.sort);
31+
}
32+
2533
handleRemotePageChange() {
2634
this.props.onTableChange('pagination', this.getNewestState());
2735
}
@@ -34,4 +42,8 @@ export default ExtendBase =>
3442
}
3543
this.props.onTableChange('filter', this.getNewestState(newState));
3644
}
45+
46+
handleSortChange() {
47+
this.props.onTableChange('sort', this.getNewestState());
48+
}
3749
};

‎packages/react-bootstrap-table2/src/sort/wrapper.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/* eslint react/prop-types: 0 */
22
import React, { Component } from 'react';
33
import PropTypes from 'prop-types';
4+
import remoteResolver from '../props-resolver/remote-resolver';
45

56
export default Base =>
6-
class SortWrapper extends Component {
7+
class SortWrapper extends remoteResolver(Component) {
78
static propTypes = {
89
store: PropTypes.object.isRequired
910
}
@@ -22,7 +23,13 @@ export default Base =>
2223
const order = defaultSorted[0].order;
2324
const column = columns.filter(col => col.dataField === dataField);
2425
if (column.length > 0) {
25-
store.sortBy(column[0], order);
26+
store.setSort(column[0], order);
27+
28+
if (this.isRemoteSort() || this.isRemotePagination()) {
29+
this.handleSortChange();
30+
} else {
31+
store.sortBy(column[0]);
32+
}
2633
}
2734
}
2835
}
@@ -32,15 +39,21 @@ export default Base =>
3239
const sortedColumn = nextProps.columns.find(
3340
column => column.dataField === nextProps.store.sortField);
3441
if (sortedColumn) {
35-
nextProps.store.sortBy(sortedColumn,nextProps.store.sortOrder);
42+
nextProps.store.sortBy(sortedColumn);
3643
}
3744
}
3845
}
3946

4047
handleSort(column) {
4148
const { store } = this.props;
42-
store.sortBy(column);
43-
this.forceUpdate();
49+
store.setSort(column);
50+
51+
if (this.isRemoteSort() || this.isRemotePagination()) {
52+
this.handleSortChange();
53+
} else {
54+
store.sortBy(column);
55+
this.forceUpdate();
56+
}
4457
}
4558

4659
render() {

‎packages/react-bootstrap-table2/src/store/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ export default class Store {
2121
if (row) _.set(row, dataField, newValue);
2222
}
2323

24-
sortBy({ dataField, sortFunc }, order) {
24+
setSort({ dataField }, order) {
2525
this.sortOrder = nextOrder(this)(dataField, order);
2626
this.sortField = dataField;
27+
}
28+
29+
sortBy({ sortFunc }) {
2730
this.data = sort(this)(sortFunc);
2831
}
2932

‎packages/react-bootstrap-table2/test/props-resolver/remote-resolver.test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,52 @@ describe('remoteResolver', () => {
102102
});
103103
});
104104

105+
describe('isRemoteSort', () => {
106+
describe('when remote is false', () => {
107+
beforeEach(() => {
108+
shallowContainer();
109+
});
110+
111+
it('should return false', () => {
112+
expect(wrapper.instance().isRemoteSort()).toBeFalsy();
113+
});
114+
});
115+
116+
describe('when remote is true', () => {
117+
beforeEach(() => {
118+
shallowContainer({ remote: true });
119+
});
120+
121+
it('should return true', () => {
122+
expect(wrapper.instance().isRemoteSort()).toBeTruthy();
123+
});
124+
});
125+
126+
describe('when remote.sort is true', () => {
127+
beforeEach(() => {
128+
shallowContainer({ remote: { sort: true } });
129+
});
130+
131+
it('should return true', () => {
132+
expect(wrapper.instance().isRemoteSort()).toBeTruthy();
133+
});
134+
});
135+
});
136+
137+
describe('handleSortChange', () => {
138+
const onTableChangeCB = sinon.stub();
139+
beforeEach(() => {
140+
onTableChangeCB.reset();
141+
shallowContainer({ onTableChange: onTableChangeCB });
142+
wrapper.instance().handleSortChange();
143+
});
144+
145+
it('should calling props.onTableChange correctly', () => {
146+
expect(onTableChangeCB.calledOnce).toBeTruthy();
147+
expect(onTableChangeCB.calledWith('sort', wrapper.instance().getNewestState())).toBeTruthy();
148+
});
149+
});
150+
105151
describe('handleRemotePageChange', () => {
106152
const onTableChangeCB = sinon.stub();
107153
beforeEach(() => {

‎packages/react-bootstrap-table2/test/sort/wrapper.test.js

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,28 +57,78 @@ describe('SortWrapper', () => {
5757
});
5858

5959
describe('call handleSort function', () => {
60+
let sortBySpy;
6061
const sortColumn = columns[0];
62+
6163
beforeEach(() => {
6264
store = new Store(keyField);
6365
store.data = data;
64-
wrapper = shallow(
65-
<SortWrapper
66-
keyField={ keyField }
67-
data={ data }
68-
columns={ columns }
69-
store={ store }
70-
/>
71-
);
72-
wrapper.instance().handleSort(sortColumn);
66+
sortBySpy = sinon.spy(store, 'sortBy');
7367
});
7468

75-
it('should operating on store correctly', () => {
76-
expect(store.sortOrder).toEqual(Const.SORT_DESC);
77-
expect(store.sortField).toEqual(sortColumn.dataField);
69+
describe('when remote.sort is false', () => {
70+
beforeEach(() => {
71+
wrapper = shallow(
72+
<SortWrapper
73+
keyField={ keyField }
74+
data={ data }
75+
columns={ columns }
76+
store={ store }
77+
/>
78+
);
79+
80+
wrapper.instance().handleSort(sortColumn);
81+
});
82+
83+
it('should operating on store correctly', () => {
84+
expect(store.sortOrder).toEqual(Const.SORT_DESC);
85+
expect(store.sortField).toEqual(sortColumn.dataField);
86+
87+
wrapper.instance().handleSort(sortColumn); // sort same column again
88+
expect(store.sortOrder).toEqual(Const.SORT_ASC);
89+
expect(store.sortField).toEqual(sortColumn.dataField);
90+
});
7891

79-
wrapper.instance().handleSort(sortColumn); // sort same column again
80-
expect(store.sortOrder).toEqual(Const.SORT_ASC);
81-
expect(store.sortField).toEqual(sortColumn.dataField);
92+
it('should calling store.sortBy correctly', () => {
93+
expect(sortBySpy.calledOnce).toBeTruthy();
94+
expect(sortBySpy.calledWith(sortColumn)).toBeTruthy();
95+
});
96+
});
97+
98+
describe('when remote.sort is true', () => {
99+
let onTableChangeCB;
100+
101+
beforeEach(() => {
102+
onTableChangeCB = sinon.stub();
103+
wrapper = shallow(
104+
<SortWrapper
105+
remote
106+
keyField={ keyField }
107+
data={ data }
108+
columns={ columns }
109+
store={ store }
110+
onTableChange={ onTableChangeCB }
111+
/>
112+
);
113+
wrapper.instance().handleSort(sortColumn);
114+
});
115+
116+
it('should operating on store correctly', () => {
117+
expect(store.sortOrder).toEqual(Const.SORT_DESC);
118+
expect(store.sortField).toEqual(sortColumn.dataField);
119+
120+
wrapper.instance().handleSort(sortColumn); // sort same column again
121+
expect(store.sortOrder).toEqual(Const.SORT_ASC);
122+
expect(store.sortField).toEqual(sortColumn.dataField);
123+
});
124+
125+
it('should not calling store.sortBy', () => {
126+
expect(sortBySpy.calledOnce).toBeFalsy();
127+
});
128+
129+
it('should calling props.onTableChange', () => {
130+
expect(onTableChangeCB.calledOnce).toBeTruthy();
131+
});
82132
});
83133
});
84134

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /