Skip to content

Commit 90bea38

Browse files
authored
Merge pull request #156 refine remote filter and pagination
Implement remote filter
2 parents 5cbeae7 + 2fbc84e commit 90bea38

File tree

12 files changed

+654
-77
lines changed

12 files changed

+654
-77
lines changed

docs/README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,21 @@ This is a chance that you can connect to your remote server or database to manip
4040
For flexibility reason, you can control what functionality should be handled on remote via a object return:
4141

4242
```js
43-
remote={ { pagination: true } }
43+
remote={ { filter: true } }
4444
```
4545

46-
In above case, only pagination will be handled on remote.
46+
In above case, only column filter will be handled on remote.
4747

4848
> Note: when remote is enable, you are suppose to give [`onTableChange`](#onTableChange) prop on `BootstrapTable`
4949
> It's the only way to communicate to your remote server and update table states.
5050
51+
A special case for remote pagination:
52+
```js
53+
remote={ { pagination: true, filter: false, sort: false } }
54+
```
55+
56+
In pagination case, even you only specified the paignation need to handle as remote, `react-bootstrap-table2` will handle all the table changes(`filter`, `sort` etc) as remote mode, because `react-bootstrap-table` only know the data of current page, but filtering, searching or sort need to work on overall datas.
57+
5158
### <a name='loading'>loading - [Bool]</a>
5259
Telling if table is loading or not, for example: waiting data loading, filtering etc. It's **only** valid when [`remote`](#remote) is enabled.
5360
When `loading` is `true`, `react-bootstrap-table` will attend to render a overlay on table via [`overlay`](#overlay) prop, if [`overlay`](#overlay) prop is not given, `react-bootstrap-table` will ignore the overlay rendering.
@@ -230,17 +237,25 @@ const columns = [ {
230237
This callback function will be called when [`remote`](#remote) enabled only.
231238

232239
```js
233-
const onTableChange = (newState) => {
240+
const onTableChange = (type, newState) => {
234241
// handle any data change here
235242
}
236243
<BootstrapTable data={ data } columns={ columns } onTableChange={ onTableChange } />
237244
```
238245

239-
There's only one argument will be passed to `onTableChange`, `newState`:
246+
There's only two arguments will be passed to `onTableChange`: `type` and `newState`:
247+
248+
`type` is tell you what kind of functionality to trigger this table's change: available values at the below:
249+
250+
* `filter`
251+
* `pagination`
252+
253+
Following is a shape of `newState`
240254

241255
```js
242256
{
243257
page, // newest page
244-
sizePerPage //newest sizePerPage
258+
sizePerPage, //newest sizePerPage
259+
filters // an object which have current filter status per column
245260
}
246261
```
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/* eslint guard-for-in: 0 */
2+
/* eslint no-restricted-syntax: 0 */
3+
import React from 'react';
4+
import PropTypes from 'prop-types';
5+
import BootstrapTable from 'react-bootstrap-table2';
6+
import paginator from 'react-bootstrap-table2-paginator';
7+
import filterFactory, { textFilter, Comparator } from 'react-bootstrap-table2-filter';
8+
import Code from 'components/common/code-block';
9+
import { productsGenerator } from 'utils/common';
10+
11+
const products = productsGenerator(87);
12+
13+
const columns = [{
14+
dataField: 'id',
15+
text: 'Product ID'
16+
}, {
17+
dataField: 'name',
18+
text: 'Product Name',
19+
filter: textFilter()
20+
}, {
21+
dataField: 'price',
22+
text: 'Product Price',
23+
filter: textFilter()
24+
}];
25+
26+
const sourceCode = `\
27+
import BootstrapTable from 'react-bootstrap-table2';
28+
import paginator from 'react-bootstrap-table2-paginator';
29+
import filterFactory, { textFilter, Comparator } from 'react-bootstrap-table2-filter';
30+
// ...
31+
32+
const columns = [{
33+
dataField: 'id',
34+
text: 'Product ID'
35+
}, {
36+
dataField: 'name',
37+
text: 'Product Name',
38+
filter: textFilter()
39+
}, {
40+
dataField: 'price',
41+
text: 'Product Price',
42+
filter: textFilter()
43+
}];
44+
45+
const RemoteAll = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
46+
<div>
47+
<BootstrapTable
48+
remote={ { pagination: true } }
49+
keyField="id"
50+
data={ data }
51+
columns={ columns }
52+
filter={ filterFactory() }
53+
pagination={ paginator({ page, sizePerPage, totalSize }) }
54+
onTableChange={ onTableChange }
55+
/>
56+
<Code>{ sourceCode }</Code>
57+
</div>
58+
);
59+
60+
RemoteAll.propTypes = {
61+
data: PropTypes.array.isRequired,
62+
page: PropTypes.number.isRequired,
63+
totalSize: PropTypes.number.isRequired,
64+
sizePerPage: PropTypes.number.isRequired,
65+
onTableChange: PropTypes.func.isRequired
66+
};
67+
68+
class Container extends React.Component {
69+
constructor(props) {
70+
super(props);
71+
this.state = {
72+
page: 1,
73+
data: products.slice(0, 10),
74+
totalSize: products.length,
75+
sizePerPage: 10
76+
};
77+
this.handleTableChange = this.handleTableChange.bind(this);
78+
}
79+
80+
handleTableChange = (type, { page, sizePerPage, filters }) => {
81+
const currentIndex = (page - 1) * sizePerPage;
82+
setTimeout(() => {
83+
const result = products.filter((row) => {
84+
let valid = true;
85+
for (const dataField in filters) {
86+
const { filterVal, filterType, comparator } = filters[dataField];
87+
88+
if (filterType === 'TEXT') {
89+
if (comparator === Comparator.LIKE) {
90+
valid = row[dataField].toString().indexOf(filterVal) > -1;
91+
} else {
92+
valid = row[dataField] === filterVal;
93+
}
94+
}
95+
if (!valid) break;
96+
}
97+
return valid;
98+
});
99+
this.setState(() => ({
100+
page,
101+
data: result.slice(currentIndex, currentIndex + sizePerPage),
102+
totalSize: result.length,
103+
sizePerPage
104+
}));
105+
}, 2000);
106+
}
107+
108+
render() {
109+
const { data, sizePerPage, page } = this.state;
110+
return (
111+
<RemoteAll
112+
data={ data }
113+
page={ page }
114+
sizePerPage={ sizePerPage }
115+
totalSize={ this.state.totalSize }
116+
onTableChange={ this.handleTableChange }
117+
/>
118+
);
119+
}
120+
}
121+
`;
122+
123+
const RemoteAll = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
124+
<div>
125+
<h3>When <code>remote.pagination</code> is enabled, the filtering,
126+
sorting and searching will also change to remote mode automatically</h3>
127+
<BootstrapTable
128+
remote={ { pagination: true } }
129+
keyField="id"
130+
data={ data }
131+
columns={ columns }
132+
filter={ filterFactory() }
133+
pagination={ paginator({ page, sizePerPage, totalSize }) }
134+
onTableChange={ onTableChange }
135+
/>
136+
<Code>{ sourceCode }</Code>
137+
</div>
138+
);
139+
140+
RemoteAll.propTypes = {
141+
data: PropTypes.array.isRequired,
142+
page: PropTypes.number.isRequired,
143+
totalSize: PropTypes.number.isRequired,
144+
sizePerPage: PropTypes.number.isRequired,
145+
onTableChange: PropTypes.func.isRequired
146+
};
147+
148+
class Container extends React.Component {
149+
constructor(props) {
150+
super(props);
151+
this.state = {
152+
page: 1,
153+
data: products.slice(0, 10),
154+
totalSize: products.length,
155+
sizePerPage: 10
156+
};
157+
this.handleTableChange = this.handleTableChange.bind(this);
158+
}
159+
160+
handleTableChange = (type, { page, sizePerPage, filters }) => {
161+
const currentIndex = (page - 1) * sizePerPage;
162+
setTimeout(() => {
163+
const result = products.filter((row) => {
164+
let valid = true;
165+
for (const dataField in filters) {
166+
const { filterVal, filterType, comparator } = filters[dataField];
167+
168+
if (filterType === 'TEXT') {
169+
if (comparator === Comparator.LIKE) {
170+
valid = row[dataField].toString().indexOf(filterVal) > -1;
171+
} else {
172+
valid = row[dataField] === filterVal;
173+
}
174+
}
175+
if (!valid) break;
176+
}
177+
return valid;
178+
});
179+
this.setState(() => ({
180+
page,
181+
data: result.slice(currentIndex, currentIndex + sizePerPage),
182+
totalSize: result.length,
183+
sizePerPage
184+
}));
185+
}, 2000);
186+
}
187+
188+
render() {
189+
const { data, sizePerPage, page } = this.state;
190+
return (
191+
<RemoteAll
192+
data={ data }
193+
page={ page }
194+
sizePerPage={ sizePerPage }
195+
totalSize={ this.state.totalSize }
196+
onTableChange={ this.handleTableChange }
197+
/>
198+
);
199+
}
200+
}
201+
202+
export default Container;
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* eslint guard-for-in: 0 */
2+
/* eslint no-restricted-syntax: 0 */
3+
import React from 'react';
4+
import PropTypes from 'prop-types';
5+
import BootstrapTable from 'react-bootstrap-table2';
6+
import filterFactory, { textFilter, Comparator } from 'react-bootstrap-table2-filter';
7+
import Code from 'components/common/code-block';
8+
import { productsGenerator } from 'utils/common';
9+
10+
const products = productsGenerator(17);
11+
12+
const columns = [{
13+
dataField: 'id',
14+
text: 'Product ID'
15+
}, {
16+
dataField: 'name',
17+
text: 'Product Name',
18+
filter: textFilter()
19+
}, {
20+
dataField: 'price',
21+
text: 'Product Price',
22+
filter: textFilter()
23+
}];
24+
25+
const sourceCode = `\
26+
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
27+
28+
const columns = [{
29+
dataField: 'id',
30+
text: 'Product ID',
31+
}, {
32+
dataField: 'name',
33+
text: 'Product Name',
34+
filter: textFilter()
35+
}, {
36+
dataField: 'price',
37+
text: 'Product Price',
38+
filter: textFilter()
39+
}];
40+
41+
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
42+
`;
43+
44+
const RemoteFilter = props => (
45+
<div>
46+
<BootstrapTable
47+
remote={ { filter: true } }
48+
keyField="id"
49+
data={ props.data }
50+
columns={ columns }
51+
filter={ filterFactory() }
52+
onTableChange={ props.onTableChange }
53+
/>
54+
<Code>{ sourceCode }</Code>
55+
</div>
56+
);
57+
58+
RemoteFilter.propTypes = {
59+
data: PropTypes.array.isRequired,
60+
onTableChange: PropTypes.func.isRequired
61+
};
62+
63+
class Container extends React.Component {
64+
constructor(props) {
65+
super(props);
66+
this.state = {
67+
data: products
68+
};
69+
}
70+
71+
handleTableChange = (type, { filters }) => {
72+
setTimeout(() => {
73+
const result = products.filter((row) => {
74+
let valid = true;
75+
for (const dataField in filters) {
76+
const { filterVal, filterType, comparator } = filters[dataField];
77+
78+
if (filterType === 'TEXT') {
79+
if (comparator === Comparator.LIKE) {
80+
valid = row[dataField].toString().indexOf(filterVal) > -1;
81+
} else {
82+
valid = row[dataField] === filterVal;
83+
}
84+
}
85+
if (!valid) break;
86+
}
87+
return valid;
88+
});
89+
this.setState(() => ({
90+
data: result
91+
}));
92+
}, 2000);
93+
}
94+
95+
render() {
96+
return (
97+
<RemoteFilter
98+
data={ this.state.data }
99+
onTableChange={ this.handleTableChange }
100+
/>
101+
);
102+
}
103+
}
104+
105+
export default Container;

packages/react-bootstrap-table2-example/examples/pagination/remote-pagination.js renamed to packages/react-bootstrap-table2-example/examples/remote/remote-pagination.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class Container extends React.Component {
105105
};
106106
}
107107

108-
handleTableChange = ({ page, sizePerPage }) => {
108+
handleTableChange = (type, { page, sizePerPage }) => {
109109
const currentIndex = (page - 1) * sizePerPage;
110110
setTimeout(() => {
111111
this.setState(() => ({

0 commit comments

Comments
 (0)