Skip to content

Commit c4eb2f8

Browse files
committed
refine remote mode on filter and pagination
1 parent e14c596 commit c4eb2f8

File tree

7 files changed

+315
-68
lines changed

7 files changed

+315
-68
lines changed

packages/react-bootstrap-table2-filter/src/wrapper.js

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
/* eslint react/prop-types: 0 */
12
import { Component } from 'react';
23
import PropTypes from 'prop-types';
34
import { filters } from './filter';
5+
import { LIKE } from './comparison';
46

57
export default class FilterWrapper extends Component {
68
static propTypes = {
79
store: PropTypes.object.isRequired,
810
columns: PropTypes.array.isRequired,
911
baseElement: PropTypes.func.isRequired,
12+
onRemoteFilterChange: PropTypes.func.isRequired,
13+
// refactoring later
1014
_: PropTypes.object.isRequired
1115
}
1216

@@ -16,28 +20,51 @@ export default class FilterWrapper extends Component {
1620
this.onFilter = this.onFilter.bind(this);
1721
}
1822

19-
componentWillReceiveProps() {
20-
this.setState(() => ({ isDataChanged: false }));
23+
componentWillReceiveProps(nextProps) {
24+
// consider to use lodash.isEqual
25+
if (JSON.stringify(this.state.currFilters) !== JSON.stringify(nextProps.store.filters)) {
26+
this.setState(() => ({ isDataChanged: true, currFilters: nextProps.store.filters }));
27+
} else {
28+
this.setState(() => ({ isDataChanged: false }));
29+
}
2130
}
2231

2332
onFilter(column, filterVal, filterType) {
24-
const { store, columns, _ } = this.props;
25-
const { currFilters } = this.state;
33+
const { store, columns, _, onRemoteFilterChange } = this.props;
34+
const currFilters = Object.assign({}, this.state.currFilters);
2635
const { dataField, filter } = column;
2736

2837
if (!_.isDefined(filterVal) || filterVal === '') {
2938
delete currFilters[dataField];
3039
} else {
31-
const { comparator } = filter.props;
40+
const { comparator = LIKE } = filter.props;
3241
currFilters[dataField] = { filterVal, filterType, comparator };
3342
}
43+
store.filters = currFilters;
3444

35-
store.filteredData = filters(store, columns, _)(currFilters);
36-
store.filtering = Object.keys(currFilters).length > 0;
45+
if (this.isRemote() || this.isPaginationRemote()) {
46+
onRemoteFilterChange(this.isPaginationRemote());
47+
// when remote filtering is enable, dont set currFilters state
48+
// in the componentWillReceiveProps, it's the key point that we can know the filter is changed
49+
return;
50+
}
3751

52+
store.filteredData = filters(store, columns, _)(currFilters);
3853
this.setState(() => ({ currFilters, isDataChanged: true }));
3954
}
4055

56+
// refactoring later
57+
isRemote() {
58+
const { remote } = this.props;
59+
return remote === true || (typeof remote === 'object' && remote.filter);
60+
}
61+
62+
// refactoring later
63+
isPaginationRemote() {
64+
const { remote } = this.props;
65+
return remote === true || (typeof remote === 'object' && remote.pagination);
66+
}
67+
4168
render() {
4269
return this.props.baseElement({
4370
...this.props,

packages/react-bootstrap-table2-filter/test/wrapper.test.js

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import sinon from 'sinon';
23
import { shallow } from 'enzyme';
34

45
import _ from 'react-bootstrap-table2/src/utils';
@@ -20,7 +21,11 @@ for (let i = 0; i < 20; i += 1) {
2021
describe('Wrapper', () => {
2122
let wrapper;
2223
let instance;
24+
const onRemoteFilterChangeCB = sinon.stub();
2325

26+
afterEach(() => {
27+
onRemoteFilterChangeCB.reset();
28+
});
2429

2530
const createTableProps = () => {
2631
const tableProps = {
@@ -40,7 +45,8 @@ describe('Wrapper', () => {
4045
data,
4146
filter: filter(),
4247
_,
43-
store: new Store('id')
48+
store: new Store('id'),
49+
onRemoteFilterChange: onRemoteFilterChangeCB
4450
};
4551
tableProps.store.data = data;
4652
return tableProps;
@@ -84,13 +90,28 @@ describe('Wrapper', () => {
8490
describe('componentWillReceiveProps', () => {
8591
let nextProps;
8692

87-
beforeEach(() => {
88-
nextProps = createTableProps();
89-
instance.componentWillReceiveProps(nextProps);
93+
describe('when props.store.filters is same as current state.currFilters', () => {
94+
beforeEach(() => {
95+
nextProps = createTableProps();
96+
instance.componentWillReceiveProps(nextProps);
97+
});
98+
99+
it('should setting isDataChanged as false (Temporary solution)', () => {
100+
expect(instance.state.isDataChanged).toBeFalsy();
101+
});
90102
});
91103

92-
it('should setting isDataChanged as false always(Temporary solution)', () => {
93-
expect(instance.state.isDataChanged).toBeFalsy();
104+
describe('when props.store.filters is different from current state.currFilters', () => {
105+
beforeEach(() => {
106+
nextProps = createTableProps();
107+
nextProps.store.filters = { price: { filterVal: 20, filterType: FILTER_TYPE.TEXT } };
108+
instance.componentWillReceiveProps(nextProps);
109+
});
110+
111+
it('should setting states correctly', () => {
112+
expect(instance.state.isDataChanged).toBeTruthy();
113+
expect(instance.state.currFilters).toBe(nextProps.store.filters);
114+
});
94115
});
95116
});
96117

@@ -126,7 +147,7 @@ describe('Wrapper', () => {
126147

127148
it('should setting store object correctly', () => {
128149
instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT);
129-
expect(props.store.filtering).toBeTruthy();
150+
expect(props.store.filters).toEqual(instance.state.currFilters);
130151
});
131152

132153
it('should setting state correctly', () => {
@@ -136,30 +157,54 @@ describe('Wrapper', () => {
136157
});
137158
});
138159

160+
describe('when remote filter is enabled', () => {
161+
const filterVal = '3';
162+
163+
beforeEach(() => {
164+
props = createTableProps();
165+
props.remote = { filter: true };
166+
createFilterWrapper(props);
167+
instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT);
168+
});
169+
170+
it('should not setting store object correctly', () => {
171+
expect(props.store.filters).not.toEqual(instance.state.currFilters);
172+
});
173+
174+
it('should not setting state', () => {
175+
expect(instance.state.isDataChanged).toBeFalsy();
176+
expect(Object.keys(instance.state.currFilters)).toHaveLength(0);
177+
});
178+
179+
it('should calling props.onRemoteFilterChange correctly', () => {
180+
expect(onRemoteFilterChangeCB.calledOnce).toBeTruthy();
181+
});
182+
});
183+
139184
describe('combination', () => {
140185
it('should setting store object correctly', () => {
141186
instance.onFilter(props.columns[1], '3', FILTER_TYPE.TEXT);
142-
expect(props.store.filtering).toBeTruthy();
187+
expect(props.store.filters).toEqual(instance.state.currFilters);
143188
expect(instance.state.isDataChanged).toBeTruthy();
144189
expect(Object.keys(instance.state.currFilters)).toHaveLength(1);
145190

146191
instance.onFilter(props.columns[1], '2', FILTER_TYPE.TEXT);
147-
expect(props.store.filtering).toBeTruthy();
192+
expect(props.store.filters).toEqual(instance.state.currFilters);
148193
expect(instance.state.isDataChanged).toBeTruthy();
149194
expect(Object.keys(instance.state.currFilters)).toHaveLength(1);
150195

151196
instance.onFilter(props.columns[2], '2', FILTER_TYPE.TEXT);
152-
expect(props.store.filtering).toBeTruthy();
197+
expect(props.store.filters).toEqual(instance.state.currFilters);
153198
expect(instance.state.isDataChanged).toBeTruthy();
154199
expect(Object.keys(instance.state.currFilters)).toHaveLength(2);
155200

156201
instance.onFilter(props.columns[2], '', FILTER_TYPE.TEXT);
157-
expect(props.store.filtering).toBeTruthy();
202+
expect(props.store.filters).toEqual(instance.state.currFilters);
158203
expect(instance.state.isDataChanged).toBeTruthy();
159204
expect(Object.keys(instance.state.currFilters)).toHaveLength(1);
160205

161206
instance.onFilter(props.columns[1], '', FILTER_TYPE.TEXT);
162-
expect(props.store.filtering).toBeFalsy();
207+
expect(props.store.filters).toEqual(instance.state.currFilters);
163208
expect(instance.state.isDataChanged).toBeTruthy();
164209
expect(Object.keys(instance.state.currFilters)).toHaveLength(0);
165210
});

packages/react-bootstrap-table2-paginator/src/wrapper.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import { getByCurrPage } from './page';
1111
class PaginationWrapper extends Component {
1212
static propTypes = {
1313
store: PropTypes.object.isRequired,
14-
baseElement: PropTypes.func.isRequired
14+
baseElement: PropTypes.func.isRequired,
15+
onRemotePageChange: PropTypes.func.isRequired
1516
}
1617

1718
constructor(props) {
@@ -43,14 +44,15 @@ class PaginationWrapper extends Component {
4344
}
4445

4546
this.state = { currPage, currSizePerPage };
47+
this.saveToStore(currPage, currSizePerPage);
4648
}
4749

4850
componentWillReceiveProps(nextProps) {
4951
let needNewState = false;
5052
let { currPage, currSizePerPage } = this.state;
51-
const { page, sizePerPage, pageStartIndex } = nextProps.pagination.options;
53+
const { page, sizePerPage, pageStartIndex, onPageChange } = nextProps.pagination.options;
5254

53-
if (typeof page !== 'undefined') { // user defined page
55+
if (typeof page !== 'undefined' && currPage !== page) { // user defined page
5456
currPage = page;
5557
needNewState = true;
5658
} else if (nextProps.isDataChanged) { // user didn't defined page but data change
@@ -63,7 +65,19 @@ class PaginationWrapper extends Component {
6365
needNewState = true;
6466
}
6567

66-
if (needNewState) this.setState(() => ({ currPage, currSizePerPage }));
68+
this.saveToStore(currPage, currSizePerPage);
69+
70+
if (needNewState) {
71+
if (onPageChange) {
72+
onPageChange(currPage, currSizePerPage);
73+
}
74+
this.setState(() => ({ currPage, currSizePerPage }));
75+
}
76+
}
77+
78+
saveToStore(page, sizePerPage) {
79+
this.props.store.page = page;
80+
this.props.store.sizePerPage = sizePerPage;
6781
}
6882

6983
isRemote() {
@@ -74,11 +88,13 @@ class PaginationWrapper extends Component {
7488
handleChangePage(currPage) {
7589
const { currSizePerPage } = this.state;
7690
const { pagination: { options }, onRemotePageChange } = this.props;
91+
this.saveToStore(currPage, currSizePerPage);
92+
7793
if (options.onPageChange) {
7894
options.onPageChange(currPage, currSizePerPage);
7995
}
8096
if (this.isRemote()) {
81-
onRemotePageChange(currPage, currSizePerPage);
97+
onRemotePageChange();
8298
return;
8399
}
84100
this.setState(() => {
@@ -90,11 +106,13 @@ class PaginationWrapper extends Component {
90106

91107
handleChangeSizePerPage(currSizePerPage, currPage) {
92108
const { pagination: { options }, onRemotePageChange } = this.props;
109+
this.saveToStore(currPage, currSizePerPage);
110+
93111
if (options.onSizePerPageChange) {
94112
options.onSizePerPageChange(currSizePerPage, currPage);
95113
}
96114
if (this.isRemote()) {
97-
onRemotePageChange(currPage, currSizePerPage);
115+
onRemotePageChange();
98116
return;
99117
}
100118
this.setState(() => {

0 commit comments

Comments
 (0)