Skip to content

Commit da86b4a

Browse files
authored
Merge pull request #1087 from react-bootstrap-table/develop
20190908 release
2 parents bb42514 + 7d28d46 commit da86b4a

File tree

33 files changed

+554
-246
lines changed

33 files changed

+554
-246
lines changed

docs/columns.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Available properties in a column object:
1313
* [formatExtraData](#formatExtraData)
1414
* [type](#type)
1515
* [sort](#sort)
16+
* [sortValue](#sortValue)
1617
* [sortFunc](#sortFunc)
1718
* [sortCaret](#sortCaret)
1819
* [onSort](#onSort)
@@ -141,8 +142,42 @@ Specify the data type on column. Available value so far is `string`, `number`, `
141142
## <a name='sort'>column.sort - [Bool]</a>
142143
Enable the column sort via a `true` value given.
143144

145+
## <a name='sortValue'>column.sortValue - [Function]</a>
146+
`column.sortValue` only work when `column.sort` enabled. This prop allow you to replace the value when table sorting.
147+
148+
For example, consider following data:
149+
150+
```js
151+
const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money'];
152+
const data = [{id: 1, type: 2}, {id: 2, type: 1}, {id: 3, type:0}];
153+
const columns = [{
154+
dataField: 'id',
155+
text: 'Job ID'
156+
}, {
157+
dataField: 'type',
158+
text: 'Job Type'
159+
sort: true,
160+
formatter: (cell, row) => types[cell]
161+
}]
162+
```
163+
164+
In above case, when user try to sort Job Type column which will sort the original value: 0, 1, 2 but we display the type name via [`column.formatter`](#formatter), which will lead confuse because we are sorting by type value instead of type name. So `sortValue` is a way for you to decide what kind of value should be adopted when sorting on a specify column:
165+
166+
```js
167+
const columns = [{
168+
dataField: 'id',
169+
text: 'Job ID'
170+
}, {
171+
dataField: 'type',
172+
text: 'Job Type'
173+
sort: true,
174+
formatter: (cell, row) => types[cell],
175+
sortValue: (cell, row) => types[cell] // we use type name to sort.
176+
}]
177+
```
178+
144179
## <a name='sortFunc'>column.sortFunc - [Function]</a>
145-
`column.sortFunc` only work when `column.sort` is enable. `sortFunc` allow you to define your sorting algorithm. This callback function accept six arguments:
180+
`column.sortFunc` only work when `column.sort` enabled. `sortFunc` allow you to define your sorting algorithm. This callback function accept six arguments:
146181

147182
```js
148183
{
@@ -421,7 +456,7 @@ If the events is not listed above, the callback function will only pass the `eve
421456
{
422457
// omit...
423458
headerEvents: {
424-
onClick: e => { ... }
459+
onClick: (e, column, columnIndex) => { ... }
425460
}
426461
}
427462
```
@@ -631,7 +666,7 @@ It's also available to custom via a callback function:
631666
{
632667
// omit...
633668
footerEvents: {
634-
onClick: e => { ... }
669+
onClick: (e, column, columnIndex) => { ... }
635670
}
636671
}
637672
```

packages/react-bootstrap-table2-editor/src/context.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
/* eslint disable-next-line: 0 */
12
/* eslint react/prop-types: 0 */
23
/* eslint react/require-default-props: 0 */
4+
/* eslint camelcase: 0 */
5+
/* eslint react/no-unused-prop-types: 0 */
36
import React from 'react';
47
import PropTypes from 'prop-types';
58
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
@@ -43,7 +46,7 @@ export default (
4346
};
4447
}
4548

46-
componentWillReceiveProps(nextProps) {
49+
UNSAFE_componentWillReceiveProps(nextProps) {
4750
if (nextProps.cellEdit && isRemoteCellEdit()) {
4851
if (nextProps.cellEdit.options.errorMessage) {
4952
this.setState(() => ({

packages/react-bootstrap-table2-editor/src/editing-cell.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* eslint no-return-assign: 0 */
33
/* eslint class-methods-use-this: 0 */
44
/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
5+
/* eslint camelcase: 0 */
56
import React, { Component } from 'react';
67
import cs from 'classnames';
78
import PropTypes from 'prop-types';
@@ -51,7 +52,11 @@ export default (_, onStartEdit) =>
5152
};
5253
}
5354

54-
componentWillReceiveProps({ message }) {
55+
componentWillUnmount() {
56+
this.clearTimer();
57+
}
58+
59+
UNSAFE_componentWillReceiveProps({ message }) {
5560
if (_.isDefined(message)) {
5661
this.createTimer();
5762
this.setState(() => ({
@@ -60,10 +65,6 @@ export default (_, onStartEdit) =>
6065
}
6166
}
6267

63-
componentWillUnmount() {
64-
this.clearTimer();
65-
}
66-
6768
clearTimer() {
6869
if (this.indicatorTimer) {
6970
clearTimeout(this.indicatorTimer);

packages/react-bootstrap-table2-editor/test/context.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ describe('CellEditContext', () => {
117117
wrapper = shallow(shallowContext());
118118
wrapper.setState(initialState);
119119
wrapper.render();
120-
wrapper.instance().componentWillReceiveProps({});
120+
wrapper.instance().UNSAFE_componentWillReceiveProps({});
121121
});
122122

123123
it('should not set state.message', () => {
@@ -138,7 +138,7 @@ describe('CellEditContext', () => {
138138
wrapper = shallow(shallowContext());
139139
wrapper.setState(initialState);
140140
wrapper.render();
141-
wrapper.instance().componentWillReceiveProps({
141+
wrapper.instance().UNSAFE_componentWillReceiveProps({
142142
cellEdit: cellEditFactory(defaultCellEdit)
143143
});
144144
});
@@ -164,7 +164,7 @@ describe('CellEditContext', () => {
164164
wrapper = shallow(shallowContext(defaultCellEdit, true));
165165
wrapper.setState(initialState);
166166
wrapper.render();
167-
wrapper.instance().componentWillReceiveProps({
167+
wrapper.instance().UNSAFE_componentWillReceiveProps({
168168
cellEdit: cellEditFactory({
169169
...defaultCellEdit,
170170
errorMessage: message
@@ -190,7 +190,7 @@ describe('CellEditContext', () => {
190190
beforeEach(() => {
191191
wrapper = shallow(shallowContext(defaultCellEdit, true));
192192
wrapper.setState(initialState);
193-
wrapper.instance().componentWillReceiveProps({
193+
wrapper.instance().UNSAFE_componentWillReceiveProps({
194194
cellEdit: cellEditFactory({ ...defaultCellEdit })
195195
});
196196
wrapper.update();

packages/react-bootstrap-table2-example/examples/footer/column-event-table.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const columns = [{
1212
dataField: 'id',
1313
text: 'Product ID',
1414
footerEvents: {
15-
onClick: () => alert('Click on Product ID footer column')
15+
onClick: (e, column, columnIndex) => alert(`Click on Product ID header column, columnIndex: ${columnIndex}`)
1616
},
1717
footer: 'Footer 1'
1818
}, {
@@ -32,7 +32,7 @@ const columns = [{
3232
dataField: 'id',
3333
text: 'Product ID',
3434
footerEvents: {
35-
onClick: () => alert('Click on Product ID footer column')
35+
onClick: (e, column, columnIndex) => alert('Click on Product ID footer column')
3636
},
3737
footer: 'Footer 1'
3838
}, {

packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const columns = [{
1212
dataField: 'id',
1313
text: 'Product ID',
1414
headerEvents: {
15-
onClick: () => alert('Click on Product ID header column')
15+
onClick: (e, column, columnIndex) => alert(`Click on Product ID header column, columnIndex: ${columnIndex}`)
1616
}
1717
}, {
1818
dataField: 'name',
@@ -29,7 +29,7 @@ const columns = [{
2929
dataField: 'id',
3030
text: 'Product ID',
3131
headerEvents: {
32-
onClick: () => alert('Click on Product ID header column')
32+
onClick: (e, column, columnIndex) => alert('Click on Product ID header column')
3333
}
3434
}, {
3535
dataField: 'name',
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* eslint react/prop-types: 0 */
2+
/* eslint no-unused-vars: 0 */
3+
import React from 'react';
4+
5+
import BootstrapTable from 'react-bootstrap-table-next';
6+
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
7+
import Code from 'components/common/code-block';
8+
import { productsGenerator } from 'utils/common';
9+
10+
const { SearchBar } = Search;
11+
const products = productsGenerator();
12+
13+
const columns = [{
14+
dataField: 'id',
15+
text: 'Product ID'
16+
}, {
17+
dataField: 'name',
18+
text: 'Product Name'
19+
}, {
20+
dataField: 'price',
21+
text: 'Product Price'
22+
}];
23+
24+
const sourceCode = `\
25+
import BootstrapTable from 'react-bootstrap-table-next';
26+
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
27+
28+
const { SearchBar } = Search;
29+
const columns = [{
30+
dataField: 'id',
31+
text: 'Product ID'
32+
}, {
33+
dataField: 'name',
34+
text: 'Product Name'
35+
}, {
36+
dataField: 'price',
37+
text: 'Product Price'
38+
}];
39+
40+
// Implement startWith instead of contain
41+
function customMatchFunc({
42+
searchText,
43+
value,
44+
column,
45+
row
46+
}) {
47+
if (typeof value !== 'undefined') {
48+
return value.startsWith(searchText);
49+
}
50+
return false;
51+
}
52+
53+
export default () => (
54+
<div>
55+
<ToolkitProvider
56+
keyField="id"
57+
data={ products }
58+
columns={ columns }
59+
search={ { customMatchFunc } }
60+
>
61+
{
62+
props => (
63+
<div>
64+
<h3>Input something at below input field:</h3>
65+
<SearchBar { ...props.searchProps } />
66+
<hr />
67+
<BootstrapTable
68+
{ ...props.baseProps }
69+
/>
70+
</div>
71+
)
72+
}
73+
</ToolkitProvider>
74+
<Code>{ sourceCode }</Code>
75+
</div>
76+
);
77+
`;
78+
79+
// Implement startWith instead of contain
80+
function customMatchFunc({
81+
searchText,
82+
value,
83+
column,
84+
row
85+
}) {
86+
if (typeof value !== 'undefined') {
87+
return `${value}`.toLowerCase().startsWith(searchText.toLowerCase());
88+
}
89+
return false;
90+
}
91+
92+
export default () => (
93+
<div>
94+
<h1>Custom a search match function by startWith instead of contain</h1>
95+
<ToolkitProvider
96+
keyField="id"
97+
data={ products }
98+
columns={ columns }
99+
search={ { onColumnMatch: customMatchFunc } }
100+
>
101+
{
102+
props => (
103+
<div>
104+
<h3>Input something at below input field:</h3>
105+
<SearchBar { ...props.searchProps } />
106+
<hr />
107+
<BootstrapTable
108+
{ ...props.baseProps }
109+
/>
110+
</div>
111+
)
112+
}
113+
</ToolkitProvider>
114+
<Code>{ sourceCode }</Code>
115+
</div>
116+
);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* eslint no-unused-vars: 0 */
2+
import React from 'react';
3+
4+
import BootstrapTable from 'react-bootstrap-table-next';
5+
import Code from 'components/common/code-block';
6+
import { jobsGenerator1 } from 'utils/common';
7+
8+
const jobs = jobsGenerator1(8);
9+
10+
const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money'];
11+
12+
const columns = [{
13+
dataField: 'id',
14+
text: 'Job ID'
15+
}, {
16+
dataField: 'name',
17+
text: 'Job Name'
18+
}, {
19+
dataField: 'owner',
20+
text: 'Job Owner'
21+
}, {
22+
dataField: 'type',
23+
text: 'Job Type',
24+
sort: true,
25+
formatter: (cell, row) => types[cell],
26+
sortValue: (cell, row) => types[cell]
27+
}];
28+
29+
const sourceCode = `\
30+
import BootstrapTable from 'react-bootstrap-table-next';
31+
32+
const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money'];
33+
34+
const columns = [{
35+
dataField: 'id',
36+
text: 'Job ID'
37+
}, {
38+
dataField: 'name',
39+
text: 'Job Name'
40+
}, {
41+
dataField: 'owner',
42+
text: 'Job Owner'
43+
}, {
44+
dataField: 'type',
45+
text: 'Job Type',
46+
sort: true,
47+
formatter: (cell, row) => types[cell],
48+
sortValue: (cell, row) => types[cell]
49+
}];
50+
51+
<BootstrapTable keyField='id' data={ products } columns={ columns } />
52+
`;
53+
54+
export default class Test extends React.Component {
55+
constructor(props) {
56+
super(props);
57+
this.state = { data: jobs };
58+
}
59+
60+
handleClick = () => {
61+
this.setState(() => {
62+
const newProducts = jobsGenerator1(21);
63+
return {
64+
data: newProducts
65+
};
66+
});
67+
}
68+
69+
render() {
70+
return (
71+
<div>
72+
<button className="btn btn-default" onClick={ this.handleClick }>Change Data</button>
73+
<BootstrapTable keyField="id" data={ this.state.data } columns={ columns } />
74+
<Code>{ sourceCode }</Code>
75+
</div>
76+
);
77+
}
78+
}

packages/react-bootstrap-table2-example/src/utils/common.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export const withOnSale = rows => rows.map((row) => {
2929
return row;
3030
});
3131

32+
export const withRandomPrice = rows => rows.map((row) => {
33+
row.price = Math.floor((Math.random() * 10) + 2000);
34+
return row;
35+
});
36+
3237
export const productsQualityGenerator = (quantity = 5, factor = 0) =>
3338
Array.from({ length: quantity }, (value, index) => ({
3439
id: index + factor,

0 commit comments

Comments
 (0)