mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 13:40:07 +00:00
Compare commits
34 Commits
react-boot
...
react-boot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cd8efffb9 | ||
|
|
447d69cae5 | ||
|
|
cacc28e1bc | ||
|
|
d7f84a9da5 | ||
|
|
63c2630f46 | ||
|
|
903dd2e5c8 | ||
|
|
964faa53e3 | ||
|
|
8fb5364cc2 | ||
|
|
8b89b3de0e | ||
|
|
4506a3dea2 | ||
|
|
ecea3efdaa | ||
|
|
8bef7eb348 | ||
|
|
408a004f58 | ||
|
|
bf46dfa026 | ||
|
|
f1b39e3dd6 | ||
|
|
029cd3ab6f | ||
|
|
1c68892a7b | ||
|
|
1bf3fa50db | ||
|
|
9988e790c1 | ||
|
|
bb071c98f9 | ||
|
|
9c5d8aac62 | ||
|
|
7c79b64985 | ||
|
|
16f89989f0 | ||
|
|
58cfdacfd1 | ||
|
|
78d5164056 | ||
|
|
bd2ce5abf0 | ||
|
|
416fcf08d4 | ||
|
|
0c650c0682 | ||
|
|
7d30804da9 | ||
|
|
782c630e58 | ||
|
|
22cc79961f | ||
|
|
a83b3d0d78 | ||
|
|
340ddb8722 | ||
|
|
32e455e65f |
166
docs/columns.md
166
docs/columns.md
@@ -30,6 +30,14 @@ Available properties in a column object:
|
|||||||
* [headerAttrs](#headerAttrs)
|
* [headerAttrs](#headerAttrs)
|
||||||
* [headerSortingClasses](#headerSortingClasses)
|
* [headerSortingClasses](#headerSortingClasses)
|
||||||
* [headerSortingStyle](#headerSortingStyle)
|
* [headerSortingStyle](#headerSortingStyle)
|
||||||
|
* [footer](#footer)
|
||||||
|
* [footerFormatter](#footerFormatter)
|
||||||
|
* [footerClasses](#footerClasses)
|
||||||
|
* [footerStyle](#footerStyle)
|
||||||
|
* [footerTitle](#footerTitle)
|
||||||
|
* [footerEvents](#footerEvents)
|
||||||
|
* [footerAlign](#footerAlign)
|
||||||
|
* [footerAttrs](#footerAttrs)
|
||||||
* [editable](#editable)
|
* [editable](#editable)
|
||||||
* [validator](#validator)
|
* [validator](#validator)
|
||||||
* [editCellStyle](#editCellStyle)
|
* [editCellStyle](#editCellStyle)
|
||||||
@@ -302,7 +310,7 @@ A new `Object` will be the result of element headerStyle.
|
|||||||
A new `String` will be the result of element title.
|
A new `String` will be the result of element title.
|
||||||
|
|
||||||
## <a name='headerTitle'>column.headerTitle - [Bool | Function]</a>
|
## <a name='headerTitle'>column.headerTitle - [Bool | Function]</a>
|
||||||
`headerTitle` is only for the title on header column, default is disable. The usage almost same as [`column.title`](#title),
|
Configure the title on header column, default is disable. The usage almost same as [`column.title`](#title),
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
@@ -518,6 +526,162 @@ const sortingHeaderStyle = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <a name='footer'>footer - [String | Function]</a>
|
||||||
|
Give a string to render the string value on the footer column.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerAlign: 'center',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, .....];
|
||||||
|
```
|
||||||
|
|
||||||
|
This prop also accept a function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: column => column.reduce((acc, item) => acc + item, 0)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## <a name='footerFormatter'>column.footerFormatter - [Function]</a>
|
||||||
|
`footerFormatter` allow you to customize the table footer column and only accept a callback function which take two arguments and a JSX/String are expected for return.
|
||||||
|
|
||||||
|
* `column`
|
||||||
|
* `columnIndex`
|
||||||
|
|
||||||
|
## <a name='footerClasses'>column.footerClasses - [String | Function]</a>
|
||||||
|
It's similar to [`column.classes`](#classes), `footerClasses` is available to have customized class on table footer column:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerClasses: 'id-custom-cell'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Furthermore, it also accept a callback function which takes 2 arguments and a `String` is expect to return:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
footerClasses: function callback(column, colIndex) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
* `column`: The value of current column.
|
||||||
|
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
|
||||||
|
|
||||||
|
## <a name='footerStyle'>column.footerStyle - [Object | Function]</a>
|
||||||
|
Customized the inline-style on table footer column:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerStyle: { backgroundColor: 'green' }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Moreover, it also accept a callback function which takes **2** arguments and an `Object` is expect to return:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
footerStyle: function callback(column, colIndex) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
* `column`: The value of current column.
|
||||||
|
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
|
||||||
|
|
||||||
|
## <a name='footerTitle'>column.footerTitle - [Bool | Function]</a>
|
||||||
|
Configure the title on footer column, default is disable. The usage is almost same as [`column.title`](#title),
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerTitle: true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It's also available to custom via a callback function:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
footerTitle: function callback(column, colIndex) { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
* `column`: The value of current column.
|
||||||
|
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
|
||||||
|
|
||||||
|
## <a name='footerEvents'>column.footerEvents - [Object]</a>
|
||||||
|
`footerEvents` same as [`column.events`](#events) but it is for footer column:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerEvents: {
|
||||||
|
onClick: e => { ... }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## <a name='footerAlign'>column.footerAlign - [String | Function]</a>
|
||||||
|
It's almost same as [`column.align`](#align), but it's for the [CSS text-align](https://www.w3schools.com/cssref/pr_text_text-align.asp) on footer column.
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerAlign: 'center'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, you can custom the align by a callback function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerAlign: (column, colIndex) => {
|
||||||
|
// column is an object and perform itself
|
||||||
|
// return custom title here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**Parameters**
|
||||||
|
* `column`: The value of current column.
|
||||||
|
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
|
||||||
|
|
||||||
|
## <a name='footerAttrs'>column.footerAttrs - [Object | Function]</a>
|
||||||
|
`footerAttrs` is similar to [`column.attrs`](#attrs) but it works for footer column.
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerAttrs: {
|
||||||
|
title: 'bar',
|
||||||
|
'data-test': 'foo'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, customize the header attributes by a **2** arguments callback function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
footerAttrs: (column, colIndex) => ({
|
||||||
|
// return customized HTML attribute here
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
* `column`: The value of current column.
|
||||||
|
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
|
||||||
|
|
||||||
## <a name='editable'>column.editable - [Bool | Function]</a>
|
## <a name='editable'>column.editable - [Bool | Function]</a>
|
||||||
`column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`.
|
`column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`.
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ Remember to install [`react-bootstrap-table2-paginator`](https://www.npmjs.com/p
|
|||||||
|
|
||||||
- [x] Custom search component and position
|
- [x] Custom search component and position
|
||||||
- [x] Custom search value
|
- [x] Custom search value
|
||||||
- [ ] Clear search
|
- [x] Clear search
|
||||||
- [ ] Multiple search
|
- [ ] Multiple search
|
||||||
- [ ] Strict search
|
- [ ] Strict search
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
* [showExpandColumn](#showExpandColumn)
|
* [showExpandColumn](#showExpandColumn)
|
||||||
* [onlyOneExpanding](#onlyOneExpanding)
|
* [onlyOneExpanding](#onlyOneExpanding)
|
||||||
* [expandByColumnOnly](#expandByColumnOnly)
|
* [expandByColumnOnly](#expandByColumnOnly)
|
||||||
|
* [expandColumnPosition](#expandColumnPosition)
|
||||||
* [expandColumnRenderer](#expandColumnRenderer)
|
* [expandColumnRenderer](#expandColumnRenderer)
|
||||||
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
|
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
|
||||||
|
|
||||||
@@ -153,3 +154,14 @@ const expandRow = {
|
|||||||
expandByColumnOnly: true
|
expandByColumnOnly: true
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <a name='expandColumnPosition'>expandRow.expandColumnPosition - [String]</a>
|
||||||
|
Default is `left`. You can give this as `right` for rendering expand column in the right side.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const expandRow = {
|
||||||
|
renderer: (row) => ...,
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandColumnPosition: 'right'
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
import filterFactory, { textFilter, dateFilter } from 'react-bootstrap-table2-filter';
|
||||||
import Code from 'components/common/code-block';
|
import Code from 'components/common/code-block';
|
||||||
import { productsGenerator } from 'utils/common';
|
import { stockGenerator } from 'utils/common';
|
||||||
|
|
||||||
const products = productsGenerator(8);
|
const products = stockGenerator(8);
|
||||||
|
|
||||||
let nameFilter;
|
let nameFilter;
|
||||||
let priceFilter;
|
let priceFilter;
|
||||||
|
let stockDateFilter;
|
||||||
|
|
||||||
const columns = [{
|
const columns = [{
|
||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
@@ -22,25 +23,36 @@ const columns = [{
|
|||||||
})
|
})
|
||||||
}, {
|
}, {
|
||||||
dataField: 'price',
|
dataField: 'price',
|
||||||
text: 'Product Price',
|
text: 'Price',
|
||||||
filter: textFilter({
|
filter: textFilter({
|
||||||
getFilter: (filter) => {
|
getFilter: (filter) => {
|
||||||
priceFilter = filter;
|
priceFilter = filter;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}, {
|
||||||
|
dataField: 'inStockDate',
|
||||||
|
text: 'InStock Date',
|
||||||
|
formatter: cell => cell.toString(),
|
||||||
|
filter: dateFilter({
|
||||||
|
getFilter: (filter) => {
|
||||||
|
stockDateFilter = filter;
|
||||||
|
}
|
||||||
|
})
|
||||||
}];
|
}];
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
nameFilter('');
|
nameFilter('');
|
||||||
priceFilter('');
|
priceFilter('');
|
||||||
|
stockDateFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
const sourceCode = `\
|
const sourceCode = `\
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
import filterFactory, { textFilter, dateFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
let nameFilter;
|
let nameFilter;
|
||||||
let priceFilter;
|
let priceFilter;
|
||||||
|
let stockDateFilter;
|
||||||
|
|
||||||
const columns = [{
|
const columns = [{
|
||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
@@ -55,17 +67,27 @@ const columns = [{
|
|||||||
})
|
})
|
||||||
}, {
|
}, {
|
||||||
dataField: 'price',
|
dataField: 'price',
|
||||||
text: 'Product Price',
|
text: 'Price',
|
||||||
filter: textFilter({
|
filter: textFilter({
|
||||||
getFilter: (filter) => {
|
getFilter: (filter) => {
|
||||||
priceFilter = filter;
|
priceFilter = filter;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}, {
|
||||||
|
dataField: 'inStockDate',
|
||||||
|
text: 'InStock Date',
|
||||||
|
formatter: cell => cell.toString(),
|
||||||
|
filter: dateFilter({
|
||||||
|
getFilter: (filter) => {
|
||||||
|
stockDateFilter = filter;
|
||||||
|
}
|
||||||
|
})
|
||||||
}];
|
}];
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
nameFilter('');
|
nameFilter('');
|
||||||
priceFilter('');
|
priceFilter('');
|
||||||
|
stockDateFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
|
|||||||
81
packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js
vendored
Normal file
81
packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* eslint eqeqeq: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(8);
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
class Table extends React.Component {
|
||||||
|
filterByPrice = filterVal =>
|
||||||
|
products.filter(product => product.price == filterVal);
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter({
|
||||||
|
onFilter: this.filterByPrice
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class Table extends React.Component {
|
||||||
|
filterByPrice = filterVal =>
|
||||||
|
products.filter(product => product.price == filterVal);
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter({
|
||||||
|
onFilter: this.filterByPrice
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>Implement a eq filter on product price column</h2>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
packages/react-bootstrap-table2-example/examples/column-filter/filter-hooks.js
vendored
Normal file
57
packages/react-bootstrap-table2-example/examples/column-filter/filter-hooks.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* eslint no-console: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(8);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter({
|
||||||
|
onFilter: filterVal => console.log(`Filter Value: ${filterVal}`)
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter({
|
||||||
|
onFilter: filterVal => console.log(\`Filter Value: $\{filterVal}\`)
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
53
packages/react-bootstrap-table2-example/examples/footer/column-align-table.js
vendored
Normal file
53
packages/react-bootstrap-table2-example/examples/footer/column-align-table.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerAlign: 'center',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footerAlign: (column, colIndex) => 'right',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerAlign: 'center',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footerAlign: (column, colIndex) => 'right',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
54
packages/react-bootstrap-table2-example/examples/footer/column-attrs-table.js
vendored
Normal file
54
packages/react-bootstrap-table2-example/examples/footer/column-attrs-table.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-alert: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1',
|
||||||
|
footerAttrs: { title: 'ID footer column' }
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2',
|
||||||
|
footerAttrs: (column, colIndex) => ({ 'data-test': `customized data ${colIndex}` })
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1',
|
||||||
|
footerAttrs: { title: 'ID footer column' }
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2',
|
||||||
|
footerAttrs: (column, colIndex) => ({ 'data-test': \`customized data \${colIndex}\` })
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
60
packages/react-bootstrap-table2-example/examples/footer/column-class-table.js
vendored
Normal file
60
packages/react-bootstrap-table2-example/examples/footer/column-class-table.js
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-alert: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2',
|
||||||
|
footerClasses: 'demo-row-odd'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerClasses: (column, colIndex) => {
|
||||||
|
if (colIndex % 2 === 0) return 'demo-row-even';
|
||||||
|
return 'demo-row-odd';
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2',
|
||||||
|
footerClasses: 'demo-row-odd'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerClasses: (column, colIndex) => {
|
||||||
|
if (colIndex % 2 === 0) return 'demo-row-even';
|
||||||
|
return 'demo-row-odd';
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
56
packages/react-bootstrap-table2-example/examples/footer/column-event-table.js
vendored
Normal file
56
packages/react-bootstrap-table2-example/examples/footer/column-event-table.js
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-alert: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerEvents: {
|
||||||
|
onClick: () => alert('Click on Product ID footer column')
|
||||||
|
},
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerEvents: {
|
||||||
|
onClick: () => alert('Click on Product ID footer column')
|
||||||
|
},
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
67
packages/react-bootstrap-table2-example/examples/footer/column-format-table.js
vendored
Normal file
67
packages/react-bootstrap-table2-example/examples/footer/column-format-table.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
function priceFormatter(column, colIndex) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<strong>$$ {column.text} $$</strong>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerFormatter: priceFormatter
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
function priceFormatter(column, colIndex) {
|
||||||
|
return (
|
||||||
|
<h5><strong>$$ { column.text } $$</strong></h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
// omit...
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerFormatter: priceFormatter
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
76
packages/react-bootstrap-table2-example/examples/footer/column-style-table.js
vendored
Normal file
76
packages/react-bootstrap-table2-example/examples/footer/column-style-table.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-alert: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2',
|
||||||
|
footerStyle: {
|
||||||
|
backgroundColor: '#c8e6c9'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerStyle: (column, colIndex) => {
|
||||||
|
if (colIndex % 2 === 0) {
|
||||||
|
return {
|
||||||
|
backgroundColor: '#81c784'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
backgroundColor: '#c8e6c9'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2',
|
||||||
|
footerStyle: {
|
||||||
|
backgroundColor: '#c8e6c9'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3',
|
||||||
|
footerStyle: (column, colIndex) => {
|
||||||
|
if (colIndex % 2 === 0) {
|
||||||
|
return {
|
||||||
|
backgroundColor: '#81c784'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
backgroundColor: '#c8e6c9'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
53
packages/react-bootstrap-table2-example/examples/footer/column-title-table.js
vendored
Normal file
53
packages/react-bootstrap-table2-example/examples/footer/column-title-table.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerTitle: true,
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footerTitle: (column, colIndex) => `this is custom title for ${column.text}`,
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footerTitle: true,
|
||||||
|
footer: 'Footer 1'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footerTitle: (column, colIndex) => \`this is custom title for \${column.text}\`,
|
||||||
|
footer: 'Footer 2'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
61
packages/react-bootstrap-table2-example/examples/footer/footer-class-table.js
vendored
Normal file
61
packages/react-bootstrap-table2-example/examples/footer/footer-class-table.js
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
footerClasses="footer-class"
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } footerClasses="footer-class" />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
52
packages/react-bootstrap-table2-example/examples/footer/function-footer.js
vendored
Normal file
52
packages/react-bootstrap-table2-example/examples/footer/function-footer.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: columnData => columnData.reduce((acc, item) => acc + item, 0)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
// omit...
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: columnData => columnData.reduce((acc, item) => acc + item, 0)
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
52
packages/react-bootstrap-table2-example/examples/footer/simple-footer.js
vendored
Normal file
52
packages/react-bootstrap-table2-example/examples/footer/simple-footer.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
footer: 'Footer 2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
// omit...
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
footer: 'Footer 3'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{sourceCode}</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
139
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list-with-search.js
vendored
Normal file
139
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list-with-search.js
vendored
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(21);
|
||||||
|
const { SearchBar } = Search;
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
class Table extends React.Component {
|
||||||
|
render() {
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
paginationSize: 4,
|
||||||
|
pageStartIndex: 1,
|
||||||
|
firstPageText: 'First',
|
||||||
|
prePageText: 'Back',
|
||||||
|
nextPageText: 'Next',
|
||||||
|
lastPageText: 'Last',
|
||||||
|
nextPageTitle: 'First page',
|
||||||
|
prePageTitle: 'Pre page',
|
||||||
|
firstPageTitle: 'Next page',
|
||||||
|
lastPageTitle: 'Last page',
|
||||||
|
showTotal: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
cellEdit={ cellEditFactory() }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={
|
||||||
|
paginationFactory(options)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ contentTable }
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class Table extends React.Component {
|
||||||
|
render() {
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
paginationSize: 4,
|
||||||
|
pageStartIndex: 1,
|
||||||
|
firstPageText: 'First',
|
||||||
|
prePageText: 'Back',
|
||||||
|
nextPageText: 'Next',
|
||||||
|
lastPageText: 'Last',
|
||||||
|
nextPageTitle: 'First page',
|
||||||
|
prePageTitle: 'Pre page',
|
||||||
|
firstPageTitle: 'Next page',
|
||||||
|
lastPageTitle: 'Last page',
|
||||||
|
showTotal: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
columns={ columns }
|
||||||
|
data={ products }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
toolkitprops => (
|
||||||
|
<div>
|
||||||
|
<SearchBar { ...toolkitprops.searchProps } />
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
{ ...toolkitprops.baseProps }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={
|
||||||
|
paginationFactory(options)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ contentTable }
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
133
packages/react-bootstrap-table2-example/examples/pagination/custome-page-list-with-filter.js
vendored
Normal file
133
packages/react-bootstrap-table2-example/examples/pagination/custome-page-list-with-filter.js
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(21);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
filter: textFilter({})
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
class Table extends React.Component {
|
||||||
|
render() {
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
paginationSize: 4,
|
||||||
|
pageStartIndex: 1,
|
||||||
|
firstPageText: 'First',
|
||||||
|
prePageText: 'Back',
|
||||||
|
nextPageText: 'Next',
|
||||||
|
lastPageText: 'Last',
|
||||||
|
nextPageTitle: 'First page',
|
||||||
|
prePageTitle: 'Pre page',
|
||||||
|
firstPageTitle: 'Next page',
|
||||||
|
lastPageTitle: 'Last page',
|
||||||
|
showTotal: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
cellEdit={ cellEditFactory() }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={
|
||||||
|
paginationFactory(options)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ contentTable }
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class Table extends React.Component {
|
||||||
|
render() {
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
paginationSize: 4,
|
||||||
|
pageStartIndex: 1,
|
||||||
|
firstPageText: 'First',
|
||||||
|
prePageText: 'Back',
|
||||||
|
nextPageText: 'Next',
|
||||||
|
lastPageText: 'Last',
|
||||||
|
nextPageTitle: 'First page',
|
||||||
|
prePageTitle: 'Pre page',
|
||||||
|
firstPageTitle: 'Next page',
|
||||||
|
lastPageTitle: 'Last page',
|
||||||
|
showTotal: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={
|
||||||
|
paginationFactory(options)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ contentTable }
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
190
packages/react-bootstrap-table2-example/examples/pagination/remote-standalone-pagination.js
vendored
Normal file
190
packages/react-bootstrap-table2-example/examples/pagination/remote-standalone-pagination.js
vendored
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/* eslint react/no-multi-comp: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(87);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
// ...
|
||||||
|
const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={
|
||||||
|
paginationFactory({
|
||||||
|
custom: true,
|
||||||
|
page,
|
||||||
|
sizePerPage,
|
||||||
|
totalSize
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p>Current Page: { paginationProps.page }</p>
|
||||||
|
<p>Current SizePerPage: { paginationProps.sizePerPage }</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<BootstrapTable
|
||||||
|
remote
|
||||||
|
keyField="id"
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
onTableChange={ onTableChange }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
class Container extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
page: 1,
|
||||||
|
data: products.slice(0, 10),
|
||||||
|
sizePerPage: 10
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTableChange = (type, { page, sizePerPage }) => {
|
||||||
|
const currentIndex = (page - 1) * sizePerPage;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState(() => ({
|
||||||
|
page,
|
||||||
|
data: products.slice(currentIndex, currentIndex + sizePerPage),
|
||||||
|
sizePerPage
|
||||||
|
}));
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { data, sizePerPage, page } = this.state;
|
||||||
|
return (
|
||||||
|
<RemotePagination
|
||||||
|
data={ data }
|
||||||
|
page={ page }
|
||||||
|
sizePerPage={ sizePerPage }
|
||||||
|
totalSize={ products.length }
|
||||||
|
onTableChange={ this.handleTableChange }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={
|
||||||
|
paginationFactory({
|
||||||
|
custom: true,
|
||||||
|
page,
|
||||||
|
sizePerPage,
|
||||||
|
totalSize
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p>Current Page: { paginationProps.page }</p>
|
||||||
|
<p>Current SizePerPage: { paginationProps.sizePerPage }</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<BootstrapTable
|
||||||
|
remote
|
||||||
|
keyField="id"
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
onTableChange={ onTableChange }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
RemotePagination.propTypes = {
|
||||||
|
data: PropTypes.array.isRequired,
|
||||||
|
page: PropTypes.number.isRequired,
|
||||||
|
totalSize: PropTypes.number.isRequired,
|
||||||
|
sizePerPage: PropTypes.number.isRequired,
|
||||||
|
onTableChange: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
class Container extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
page: 1,
|
||||||
|
data: products.slice(0, 10),
|
||||||
|
sizePerPage: 10
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTableChange = (type, { page, sizePerPage }) => {
|
||||||
|
const currentIndex = (page - 1) * sizePerPage;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState(() => ({
|
||||||
|
page,
|
||||||
|
data: products.slice(currentIndex, currentIndex + sizePerPage),
|
||||||
|
sizePerPage
|
||||||
|
}));
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { data, sizePerPage, page } = this.state;
|
||||||
|
return (
|
||||||
|
<RemotePagination
|
||||||
|
data={ data }
|
||||||
|
page={ page }
|
||||||
|
sizePerPage={ sizePerPage }
|
||||||
|
totalSize={ products.length }
|
||||||
|
onTableChange={ this.handleTableChange }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Container;
|
||||||
76
packages/react-bootstrap-table2-example/examples/row-expand/expand-column-position.js
vendored
Normal file
76
packages/react-bootstrap-table2-example/examples/row-expand/expand-column-position.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsExpandRowsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsExpandRowsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandColumnPosition: 'right'
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandColumnPosition: 'right'
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField='id'
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
86
packages/react-bootstrap-table2-example/examples/search/clear-search-button.js
vendored
Normal file
86
packages/react-bootstrap-table2-example/examples/search/clear-search-button.js
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { SearchBar, ClearSearchButton } = Search;
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { SearchBar, ClearSearchButton } = Search;
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<h3>Input something at below input field:</h3>
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<ClearSearchButton { ...props.searchProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<h3>Input something at below input field:</h3>
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<ClearSearchButton { ...props.searchProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-example",
|
"name": "react-bootstrap-table2-example",
|
||||||
"version": "1.0.13",
|
"version": "1.0.16",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export const stockGenerator = (quantity = 5) =>
|
|||||||
Array.from({ length: quantity }, (value, index) => ({
|
Array.from({ length: quantity }, (value, index) => ({
|
||||||
id: index,
|
id: index,
|
||||||
name: `Todo item ${index}`,
|
name: `Todo item ${index}`,
|
||||||
|
price: Math.floor((Math.random() * 2) + 1),
|
||||||
inStockDate:
|
inStockDate:
|
||||||
new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime()))
|
new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime()))
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -45,6 +45,18 @@ import HeaderColumnStyleTable from 'examples/header-columns/column-style-table';
|
|||||||
import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
|
import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
|
||||||
import HeaderClassTable from 'examples/header-columns/header-class-table';
|
import HeaderClassTable from 'examples/header-columns/header-class-table';
|
||||||
|
|
||||||
|
// footer
|
||||||
|
import SimpleFooter from 'examples/footer/simple-footer';
|
||||||
|
import FunctionFooter from 'examples/footer/function-footer';
|
||||||
|
import FooterClassTable from 'examples/footer/footer-class-table';
|
||||||
|
import FooterColumnFormatTable from 'examples/footer/column-format-table';
|
||||||
|
import FooterColumnAlignTable from 'examples/footer/column-align-table';
|
||||||
|
import FooterColumnTitleTable from 'examples/footer/column-title-table.js';
|
||||||
|
import FooterColumnEventsTable from 'examples/footer/column-event-table.js';
|
||||||
|
import FooterColumnClassTable from 'examples/footer/column-class-table.js';
|
||||||
|
import FooterColumnStyleTable from 'examples/footer/column-style-table.js';
|
||||||
|
import FooterColumnAttrsTable from 'examples/footer/column-attrs-table.js';
|
||||||
|
|
||||||
// column filter
|
// column filter
|
||||||
import TextFilter from 'examples/column-filter/text-filter';
|
import TextFilter from 'examples/column-filter/text-filter';
|
||||||
import TextFilterWithDefaultValue from 'examples/column-filter/text-filter-default-value';
|
import TextFilterWithDefaultValue from 'examples/column-filter/text-filter-default-value';
|
||||||
@@ -74,6 +86,8 @@ import ProgrammaticallyMultiSelectFilter from 'examples/column-filter/programmat
|
|||||||
import CustomFilter from 'examples/column-filter/custom-filter';
|
import CustomFilter from 'examples/column-filter/custom-filter';
|
||||||
import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter';
|
import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter';
|
||||||
import ClearAllFilters from 'examples/column-filter/clear-all-filters';
|
import ClearAllFilters from 'examples/column-filter/clear-all-filters';
|
||||||
|
import FilterHooks from 'examples/column-filter/filter-hooks';
|
||||||
|
import CustomFilterLogic from 'examples/column-filter/custom-filter-logic';
|
||||||
|
|
||||||
// work on rows
|
// work on rows
|
||||||
import RowStyleTable from 'examples/rows/row-style';
|
import RowStyleTable from 'examples/rows/row-style';
|
||||||
@@ -141,6 +155,7 @@ import ExpandColumn from 'examples/row-expand/expand-column';
|
|||||||
import OnlyExpandByColumn from 'examples/row-expand/expand-by-column-only.js';
|
import OnlyExpandByColumn from 'examples/row-expand/expand-by-column-only.js';
|
||||||
import ExpandOnlyOne from 'examples/row-expand/expand-only-one';
|
import ExpandOnlyOne from 'examples/row-expand/expand-only-one';
|
||||||
import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
|
import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
|
||||||
|
import ExpandColumnPosition from 'examples/row-expand/expand-column-position';
|
||||||
import ExpandHooks from 'examples/row-expand/expand-hooks';
|
import ExpandHooks from 'examples/row-expand/expand-hooks';
|
||||||
|
|
||||||
// pagination
|
// pagination
|
||||||
@@ -154,9 +169,13 @@ import CustomPageListTable from 'examples/pagination/custom-page-list';
|
|||||||
import StandalonePaginationList from 'examples/pagination/standalone-pagination-list';
|
import StandalonePaginationList from 'examples/pagination/standalone-pagination-list';
|
||||||
import StandaloneSizePerPage from 'examples/pagination/standalone-size-per-page';
|
import StandaloneSizePerPage from 'examples/pagination/standalone-size-per-page';
|
||||||
import FullyCustomPaginationTable from 'examples/pagination/fully-custom-pagination';
|
import FullyCustomPaginationTable from 'examples/pagination/fully-custom-pagination';
|
||||||
|
import RemoteStandalonePaginationTable from 'examples/pagination/remote-standalone-pagination';
|
||||||
|
import CustomePaginationWithFilter from 'examples/pagination/custome-page-list-with-filter';
|
||||||
|
import CustomePaginationWithSearch from 'examples/pagination/custom-page-list-with-search';
|
||||||
|
|
||||||
// search
|
// search
|
||||||
import SearchTable from 'examples/search';
|
import SearchTable from 'examples/search';
|
||||||
|
import ClearSearchButton from 'examples/search/clear-search-button';
|
||||||
import DefaultSearch from 'examples/search/default-search';
|
import DefaultSearch from 'examples/search/default-search';
|
||||||
import DefaultCustomSearch from 'examples/search/default-custom-search';
|
import DefaultCustomSearch from 'examples/search/default-custom-search';
|
||||||
import FullyCustomSearch from 'examples/search/fully-custom-search';
|
import FullyCustomSearch from 'examples/search/fully-custom-search';
|
||||||
@@ -196,8 +215,7 @@ import '../../react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.
|
|||||||
// import bootstrap style by given version
|
// import bootstrap style by given version
|
||||||
import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style';
|
import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style';
|
||||||
|
|
||||||
storiesOf('Welcome', module)
|
storiesOf('Welcome', module).add('react bootstrap table 2 ', () => <Welcome />);
|
||||||
.add('react bootstrap table 2 ', () => <Welcome />);
|
|
||||||
|
|
||||||
storiesOf('Basic Table', module)
|
storiesOf('Basic Table', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
@@ -273,7 +291,9 @@ storiesOf('Column Filter', module)
|
|||||||
.add('Custom Filter', () => <CustomFilter />)
|
.add('Custom Filter', () => <CustomFilter />)
|
||||||
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
||||||
.add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
|
.add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
|
||||||
.add('Clear All Filters', () => <ClearAllFilters />);
|
.add('Clear All Filters', () => <ClearAllFilters />)
|
||||||
|
.add('Filter Hooks', () => <FilterHooks />)
|
||||||
|
.add('Implement custom filter logic', () => <CustomFilterLogic />);
|
||||||
|
|
||||||
storiesOf('Work on Rows', module)
|
storiesOf('Work on Rows', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
@@ -282,6 +302,19 @@ storiesOf('Work on Rows', module)
|
|||||||
.add('Hide Rows', () => <RowHiddenTable />)
|
.add('Hide Rows', () => <RowHiddenTable />)
|
||||||
.add('Row Event', () => <RowEventTable />);
|
.add('Row Event', () => <RowEventTable />);
|
||||||
|
|
||||||
|
storiesOf('Footer', module)
|
||||||
|
.addDecorator(bootstrapStyle())
|
||||||
|
.add('Simple Footer', () => <SimpleFooter />)
|
||||||
|
.add('Function Footer', () => <FunctionFooter />)
|
||||||
|
.add('Column Formatter', () => <FooterColumnFormatTable />)
|
||||||
|
.add('Column Align', () => <FooterColumnAlignTable />)
|
||||||
|
.add('Column Title', () => <FooterColumnTitleTable />)
|
||||||
|
.add('Column Events', () => <FooterColumnEventsTable />)
|
||||||
|
.add('Customize Column Class', () => <FooterColumnClassTable />)
|
||||||
|
.add('Customize Column Style', () => <FooterColumnStyleTable />)
|
||||||
|
.add('Customize Column HTML attribute', () => <FooterColumnAttrsTable />)
|
||||||
|
.add('Footer Class', () => <FooterClassTable />);
|
||||||
|
|
||||||
storiesOf('Sort Table', module)
|
storiesOf('Sort Table', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Enable Sort', () => <EnableSortTable />)
|
.add('Enable Sort', () => <EnableSortTable />)
|
||||||
@@ -346,6 +379,7 @@ storiesOf('Row Expand', module)
|
|||||||
.add('Only Expand by Indicator', () => <OnlyExpandByColumn />)
|
.add('Only Expand by Indicator', () => <OnlyExpandByColumn />)
|
||||||
.add('Expand Only One Row at The Same Time', () => <ExpandOnlyOne />)
|
.add('Expand Only One Row at The Same Time', () => <ExpandOnlyOne />)
|
||||||
.add('Custom Expand Indicator', () => <CustomExpandColumn />)
|
.add('Custom Expand Indicator', () => <CustomExpandColumn />)
|
||||||
|
.add('Expand Column Position', () => <ExpandColumnPosition />)
|
||||||
.add('Expand Hooks', () => <ExpandHooks />);
|
.add('Expand Hooks', () => <ExpandHooks />);
|
||||||
|
|
||||||
storiesOf('Pagination', module)
|
storiesOf('Pagination', module)
|
||||||
@@ -359,11 +393,15 @@ storiesOf('Pagination', module)
|
|||||||
.add('Custom SizePerPage', () => <CustomSizePerPageTable />)
|
.add('Custom SizePerPage', () => <CustomSizePerPageTable />)
|
||||||
.add('Standalone Pagination List', () => <StandalonePaginationList />)
|
.add('Standalone Pagination List', () => <StandalonePaginationList />)
|
||||||
.add('Standalone SizePerPage Dropdown', () => <StandaloneSizePerPage />)
|
.add('Standalone SizePerPage Dropdown', () => <StandaloneSizePerPage />)
|
||||||
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />);
|
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />)
|
||||||
|
.add('Remote Fully Custom Pagination', () => <RemoteStandalonePaginationTable />)
|
||||||
|
.add('Custom Pagination with Filter', () => <CustomePaginationWithFilter />)
|
||||||
|
.add('Custom Pagination with Search', () => <CustomePaginationWithSearch />);
|
||||||
|
|
||||||
storiesOf('Table Search', module)
|
storiesOf('Table Search', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Basic Search Table', () => <SearchTable />)
|
.add('Basic Search Table', () => <SearchTable />)
|
||||||
|
.add('Clear Search Button', () => <ClearSearchButton />)
|
||||||
.add('Default Search Table', () => <DefaultSearch />)
|
.add('Default Search Table', () => <DefaultSearch />)
|
||||||
.add('Default Custom Search', () => <DefaultCustomSearch />)
|
.add('Default Custom Search', () => <DefaultCustomSearch />)
|
||||||
.add('Fully Custom Search', () => <FullyCustomSearch />)
|
.add('Fully Custom Search', () => <FullyCustomSearch />)
|
||||||
|
|||||||
@@ -13,4 +13,8 @@
|
|||||||
|
|
||||||
.header-class {
|
.header-class {
|
||||||
background-color: $green-lighten-4;
|
background-color: $green-lighten-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-class {
|
||||||
|
background-color: $green-lighten-4;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-filter",
|
"name": "react-bootstrap-table2-filter",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"description": "it's a column filter addon for react-bootstrap-table2",
|
"description": "it's a column filter addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -42,10 +42,11 @@ class DateFilter extends Component {
|
|||||||
// export onFilter function to allow users to access
|
// export onFilter function to allow users to access
|
||||||
if (getFilter) {
|
if (getFilter) {
|
||||||
getFilter((filterVal) => {
|
getFilter((filterVal) => {
|
||||||
this.dateFilterComparator.value = filterVal.comparator;
|
const nullableFilterVal = filterVal || { date: null, comparator: null };
|
||||||
this.inputDate.value = dateParser(filterVal.date);
|
this.dateFilterComparator.value = nullableFilterVal.comparator;
|
||||||
|
this.inputDate.value = nullableFilterVal.date ? dateParser(nullableFilterVal.date) : null;
|
||||||
|
|
||||||
this.applyFilter(filterVal.date, filterVal.comparator);
|
this.applyFilter(nullableFilterVal.date, nullableFilterVal.comparator);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ export default (
|
|||||||
class FilterProvider extends React.Component {
|
class FilterProvider extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
columns: PropTypes.array.isRequired
|
columns: PropTypes.array.isRequired,
|
||||||
|
dataChangeListener: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -25,6 +26,9 @@ export default (
|
|||||||
this.currFilters = {};
|
this.currFilters = {};
|
||||||
this.onFilter = this.onFilter.bind(this);
|
this.onFilter = this.onFilter.bind(this);
|
||||||
this.onExternalFilter = this.onExternalFilter.bind(this);
|
this.onExternalFilter = this.onExternalFilter.bind(this);
|
||||||
|
this.state = {
|
||||||
|
data: props.data
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -33,6 +37,14 @@ export default (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (isRemoteFiltering()) {
|
||||||
|
this.setState({
|
||||||
|
data: nextProps.data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onFilter(column, filterType, initialize = false) {
|
onFilter(column, filterType, initialize = false) {
|
||||||
return (filterVal) => {
|
return (filterVal) => {
|
||||||
// watch out here if migration to context API, #334
|
// watch out here if migration to context API, #334
|
||||||
@@ -64,7 +76,17 @@ export default (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.forceUpdate();
|
let result;
|
||||||
|
if (filter.props.onFilter) {
|
||||||
|
result = filter.props.onFilter(filterVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { dataChangeListener, data } = this.props;
|
||||||
|
result = result || filters(data, this.props.columns, _)(this.currFilters);
|
||||||
|
if (dataChangeListener) {
|
||||||
|
dataChangeListener.emit('filterChanged', result.length);
|
||||||
|
}
|
||||||
|
this.setState({ data: result });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,13 +97,9 @@ export default (
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { data } = this.props;
|
|
||||||
if (!isRemoteFiltering()) {
|
|
||||||
data = filters(data, this.props.columns, _)(this.currFilters);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<FilterContext.Provider value={ {
|
<FilterContext.Provider value={ {
|
||||||
data,
|
data: this.state.data,
|
||||||
onFilter: this.onFilter,
|
onFilter: this.onFilter,
|
||||||
onExternalFilter: this.onExternalFilter
|
onExternalFilter: this.onExternalFilter
|
||||||
} }
|
} }
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ describe('FilterContext', () => {
|
|||||||
const handleFilterChange = jest.fn();
|
const handleFilterChange = jest.fn();
|
||||||
|
|
||||||
function shallowContext(
|
function shallowContext(
|
||||||
enableRemote = false
|
enableRemote = false,
|
||||||
|
tableColumns = columns,
|
||||||
|
dataChangeListener,
|
||||||
) {
|
) {
|
||||||
mockBase.mockReset();
|
mockBase.mockReset();
|
||||||
handleFilterChange.mockReset();
|
handleFilterChange.mockReset();
|
||||||
@@ -56,8 +58,9 @@ describe('FilterContext', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterContext.Provider
|
<FilterContext.Provider
|
||||||
columns={ columns }
|
columns={ tableColumns }
|
||||||
data={ data }
|
data={ data }
|
||||||
|
dataChangeListener={ dataChangeListener }
|
||||||
>
|
>
|
||||||
<FilterContext.Consumer>
|
<FilterContext.Consumer>
|
||||||
{
|
{
|
||||||
@@ -225,6 +228,84 @@ describe('FilterContext', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('if filter.props.onFilter is defined', () => {
|
||||||
|
const filterVal = '3';
|
||||||
|
const onFilter = jest.fn();
|
||||||
|
const customColumns = columns.map((column, i) => {
|
||||||
|
if (i === 1) {
|
||||||
|
return {
|
||||||
|
...column,
|
||||||
|
filter: textFilter({ onFilter })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return column;
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext(false, customColumns));
|
||||||
|
wrapper.render();
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call filter.props.onFilter correctly', () => {
|
||||||
|
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||||
|
expect(onFilter).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onFilter).toHaveBeenCalledWith(filterVal);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if filter.props.onFilter is defined and return an undefined data', () => {
|
||||||
|
const mockReturn = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'A'
|
||||||
|
}];
|
||||||
|
const filterVal = 'A';
|
||||||
|
const onFilter = jest.fn().mockReturnValue(mockReturn);
|
||||||
|
const customColumns = columns.map((column, i) => {
|
||||||
|
if (i === 1) {
|
||||||
|
return {
|
||||||
|
...column,
|
||||||
|
filter: textFilter({ onFilter })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return column;
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext(false, customColumns));
|
||||||
|
wrapper.render();
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call filter.props.onFilter correctly', () => {
|
||||||
|
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||||
|
expect(onFilter).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onFilter).toHaveBeenCalledWith(filterVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set state.data correctly', () => {
|
||||||
|
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||||
|
expect(instance.state.data).toEqual(mockReturn);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when props.dataChangeListener is defined', () => {
|
||||||
|
const filterVal = '3';
|
||||||
|
const newDataLength = 0;
|
||||||
|
const dataChangeListener = { emit: jest.fn() };
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext(false, columns, dataChangeListener));
|
||||||
|
wrapper.render();
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call dataChangeListener.emit correctly', () => {
|
||||||
|
instance.onFilter(columns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||||
|
expect(dataChangeListener.emit).toHaveBeenCalledWith('filterChanged', newDataLength);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('combination', () => {
|
describe('combination', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = shallow(shallowContext());
|
wrapper = shallow(shallowContext());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-paginator",
|
"name": "react-bootstrap-table2-paginator",
|
||||||
"version": "2.0.0",
|
"version": "2.0.2",
|
||||||
"description": "it's the pagination addon for react-bootstrap-table2",
|
"description": "it's the pagination addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -135,8 +135,8 @@ export default ExtendBase =>
|
|||||||
calculateSizePerPageStatus() {
|
calculateSizePerPageStatus() {
|
||||||
const { sizePerPageList } = this.props;
|
const { sizePerPageList } = this.props;
|
||||||
return sizePerPageList.map((_sizePerPage) => {
|
return sizePerPageList.map((_sizePerPage) => {
|
||||||
const pageText = _sizePerPage.text || _sizePerPage;
|
const pageText = typeof _sizePerPage.text !== 'undefined' ? _sizePerPage.text : _sizePerPage;
|
||||||
const pageNumber = _sizePerPage.value || _sizePerPage;
|
const pageNumber = typeof _sizePerPage.value !== 'undefined' ? _sizePerPage.value : _sizePerPage;
|
||||||
return {
|
return {
|
||||||
text: `${pageText}`,
|
text: `${pageText}`,
|
||||||
page: pageNumber
|
page: pageNumber
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
/* eslint react/require-default-props: 0 */
|
/* eslint react/require-default-props: 0 */
|
||||||
/* eslint no-lonely-if: 0 */
|
/* eslint no-lonely-if: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import EventEmitter from 'events';
|
||||||
import Const from './const';
|
import Const from './const';
|
||||||
|
import { alignPage } from './page';
|
||||||
|
|
||||||
const StateContext = React.createContext();
|
const StateContext = React.createContext();
|
||||||
|
|
||||||
@@ -10,6 +12,7 @@ class StateProvider extends React.Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.handleChangePage = this.handleChangePage.bind(this);
|
this.handleChangePage = this.handleChangePage.bind(this);
|
||||||
|
this.handleDataSizeChange = this.handleDataSizeChange.bind(this);
|
||||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||||
|
|
||||||
let currPage;
|
let currPage;
|
||||||
@@ -36,7 +39,10 @@ class StateProvider extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.currPage = currPage;
|
this.currPage = currPage;
|
||||||
|
this.dataSize = options.totalSize;
|
||||||
this.currSizePerPage = currSizePerPage;
|
this.currSizePerPage = currSizePerPage;
|
||||||
|
this.dataChangeListener = new EventEmitter();
|
||||||
|
this.dataChangeListener.on('filterChanged', this.handleDataSizeChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
@@ -46,12 +52,13 @@ class StateProvider extends React.Component {
|
|||||||
if (this.isRemotePagination() || custom) {
|
if (this.isRemotePagination() || custom) {
|
||||||
this.currPage = nextProps.pagination.options.page;
|
this.currPage = nextProps.pagination.options.page;
|
||||||
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||||
|
this.dataSize = nextProps.pagination.options.totalSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPaginationProps = () => {
|
getPaginationProps = () => {
|
||||||
const { pagination: { options }, bootstrap4 } = this.props;
|
const { pagination: { options }, bootstrap4 } = this.props;
|
||||||
const { currPage, currSizePerPage } = this;
|
const { currPage, currSizePerPage, dataSize } = this;
|
||||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||||
@@ -72,7 +79,7 @@ class StateProvider extends React.Component {
|
|||||||
hideSizePerPage,
|
hideSizePerPage,
|
||||||
alwaysShowAllBtns,
|
alwaysShowAllBtns,
|
||||||
withFirstAndLast,
|
withFirstAndLast,
|
||||||
dataSize: options.totalSize,
|
dataSize,
|
||||||
sizePerPageList: options.sizePerPageList || Const.SIZE_PER_PAGE_LIST,
|
sizePerPageList: options.sizePerPageList || Const.SIZE_PER_PAGE_LIST,
|
||||||
paginationSize: options.paginationSize || Const.PAGINATION_SIZE,
|
paginationSize: options.paginationSize || Const.PAGINATION_SIZE,
|
||||||
showTotal: options.showTotal,
|
showTotal: options.showTotal,
|
||||||
@@ -106,6 +113,20 @@ class StateProvider extends React.Component {
|
|||||||
return e.result;
|
return e.result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleDataSizeChange(newDataSize) {
|
||||||
|
const { pagination: { options } } = this.props;
|
||||||
|
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||||
|
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||||
|
this.dataSize = newDataSize;
|
||||||
|
this.currPage = alignPage(
|
||||||
|
newDataSize,
|
||||||
|
this.currPage,
|
||||||
|
this.currSizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
);
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
handleChangePage(currPage) {
|
handleChangePage(currPage) {
|
||||||
const { currSizePerPage } = this;
|
const { currSizePerPage } = this;
|
||||||
const { pagination: { options } } = this.props;
|
const { pagination: { options } } = this.props;
|
||||||
@@ -153,7 +174,8 @@ class StateProvider extends React.Component {
|
|||||||
paginationProps,
|
paginationProps,
|
||||||
paginationTableProps: {
|
paginationTableProps: {
|
||||||
pagination,
|
pagination,
|
||||||
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: this.dataChangeListener
|
||||||
}
|
}
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ describe('PaginationStateContext', () => {
|
|||||||
expect(wrapper.instance().currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[0]);
|
expect(wrapper.instance().currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should have correct dataSize', () => {
|
||||||
|
expect(wrapper.instance().dataSize).toEqual(options.totalSize);
|
||||||
|
});
|
||||||
|
|
||||||
it('should get correct pagination props', () => {
|
it('should get correct pagination props', () => {
|
||||||
const instance = wrapper.instance();
|
const instance = wrapper.instance();
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
@@ -102,7 +106,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -149,7 +154,7 @@ describe('PaginationStateContext', () => {
|
|||||||
setRemotePaginationEmitter(instance, true);
|
setRemotePaginationEmitter(instance, true);
|
||||||
nextProps = {
|
nextProps = {
|
||||||
data,
|
data,
|
||||||
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5 } }
|
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5, totalSize: 50 } }
|
||||||
};
|
};
|
||||||
instance.componentWillReceiveProps(nextProps);
|
instance.componentWillReceiveProps(nextProps);
|
||||||
});
|
});
|
||||||
@@ -157,6 +162,7 @@ describe('PaginationStateContext', () => {
|
|||||||
it('should always reset currPage and currSizePerPage', () => {
|
it('should always reset currPage and currSizePerPage', () => {
|
||||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||||
|
expect(instance.dataSize).toEqual(nextProps.pagination.options.totalSize);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -170,7 +176,10 @@ describe('PaginationStateContext', () => {
|
|||||||
setRemotePaginationEmitter(instance, true);
|
setRemotePaginationEmitter(instance, true);
|
||||||
nextProps = {
|
nextProps = {
|
||||||
data,
|
data,
|
||||||
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5, custom: true } }
|
pagination: {
|
||||||
|
...defaultPagination,
|
||||||
|
options: { page: 3, sizePerPage: 5, custom: true, totalSize: 50 }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
instance.componentWillReceiveProps(nextProps);
|
instance.componentWillReceiveProps(nextProps);
|
||||||
});
|
});
|
||||||
@@ -178,10 +187,36 @@ describe('PaginationStateContext', () => {
|
|||||||
it('should always reset currPage and currSizePerPage', () => {
|
it('should always reset currPage and currSizePerPage', () => {
|
||||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||||
|
expect(instance.dataSize).toEqual(nextProps.pagination.options.totalSize);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('handleDataSizeChange', () => {
|
||||||
|
let instance;
|
||||||
|
const newTotalSize = 8;
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext({
|
||||||
|
...defaultPagination,
|
||||||
|
page: 3
|
||||||
|
}));
|
||||||
|
instance = wrapper.instance();
|
||||||
|
setRemotePaginationEmitter(instance);
|
||||||
|
jest.spyOn(instance, 'forceUpdate');
|
||||||
|
instance.handleDataSizeChange(newTotalSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update dataSize correctly', () => {
|
||||||
|
expect(instance.dataSize).toEqual(newTotalSize);
|
||||||
|
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update currPage correctly if page list shrink', () => {
|
||||||
|
expect(instance.currPage).toEqual(Const.PAGE_START_INDEX);
|
||||||
|
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('handleChangePage', () => {
|
describe('handleChangePage', () => {
|
||||||
let instance;
|
let instance;
|
||||||
const newPage = 3;
|
const newPage = 3;
|
||||||
@@ -343,7 +378,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -374,7 +410,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -401,7 +438,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -428,7 +466,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -455,7 +494,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -482,7 +522,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -509,7 +550,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -536,7 +578,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -563,7 +606,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -590,7 +634,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -617,7 +662,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -644,7 +690,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -671,7 +718,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -698,7 +746,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -725,7 +774,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -752,7 +802,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -779,7 +830,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -806,7 +858,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -833,7 +886,8 @@ describe('PaginationStateContext', () => {
|
|||||||
createContext: expect.any(Function),
|
createContext: expect.any(Function),
|
||||||
options: instance.getPaginationProps()
|
options: instance.getPaginationProps()
|
||||||
},
|
},
|
||||||
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: instance.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: expect.any(Object)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -95,8 +95,34 @@ If you want to search on the formatted data, you are supposed to enable this pro
|
|||||||
</ToolkitProvider>
|
</ToolkitProvider>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Clear Search Button
|
||||||
|
We have a built-in clear search function which allow user clear search status via clicking button:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { SearchBar, ClearSearchButton } = Search;
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<ClearSearchButton { ...props.searchProps } />
|
||||||
|
....
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
```
|
||||||
|
|
||||||
## Export CSV
|
## Export CSV
|
||||||
There are two step to enable the export CSV functionality:
|
There are two steps to enable the export CSV functionality:
|
||||||
|
|
||||||
1. Give `exportCSV` prop as `true` on `ToolkitProvider`.
|
1. Give `exportCSV` prop as `true` on `ToolkitProvider`.
|
||||||
2. Render `ExportCSVButton` with `csvProps`. The position of `ExportCSVButton` is depends on you.
|
2. Render `ExportCSVButton` with `csvProps`. The position of `ExportCSVButton` is depends on you.
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
searchText: typeof props.search === 'object' ? (props.search.defaultSearch || '') : ''
|
searchText: typeof props.search === 'object' ? (props.search.defaultSearch || '') : ''
|
||||||
};
|
};
|
||||||
this._ = null;
|
this._ = null;
|
||||||
|
this.onClear = this.onClear.bind(this);
|
||||||
this.onSearch = this.onSearch.bind(this);
|
this.onSearch = this.onSearch.bind(this);
|
||||||
this.setDependencyModules = this.setDependencyModules.bind(this);
|
this.setDependencyModules = this.setDependencyModules.bind(this);
|
||||||
}
|
}
|
||||||
@@ -56,6 +57,10 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClear() {
|
||||||
|
this.setState({ searchText: '' });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {*} _
|
* @param {*} _
|
||||||
@@ -87,7 +92,8 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
<ToolkitContext.Provider value={ {
|
<ToolkitContext.Provider value={ {
|
||||||
searchProps: {
|
searchProps: {
|
||||||
searchText: this.state.searchText,
|
searchText: this.state.searchText,
|
||||||
onSearch: this.onSearch
|
onSearch: this.onSearch,
|
||||||
|
onClear: this.onClear
|
||||||
},
|
},
|
||||||
csvProps: {
|
csvProps: {
|
||||||
onExport: this.handleExportCSV
|
onExport: this.handleExportCSV
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-toolkit",
|
"name": "react-bootstrap-table2-toolkit",
|
||||||
"version": "1.1.1",
|
"version": "1.2.1",
|
||||||
"description": "The toolkit for react-bootstrap-table2",
|
"description": "The toolkit for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -25,13 +25,19 @@ export default Base =>
|
|||||||
let data;
|
let data;
|
||||||
if (typeof source !== 'undefined') {
|
if (typeof source !== 'undefined') {
|
||||||
data = source;
|
data = source;
|
||||||
|
} else if (options.exportAll) {
|
||||||
|
data = this.props.data;
|
||||||
} else {
|
} else {
|
||||||
data = options.exportAll ? this.props.data : this.getData();
|
const payload = {};
|
||||||
|
this.tableExposedAPIEmitter.emit('get.table.data', payload);
|
||||||
|
data = payload.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter data
|
// filter data
|
||||||
if (options.onlyExportSelection) {
|
if (options.onlyExportSelection) {
|
||||||
const selections = this.getSelected();
|
const payload = {};
|
||||||
|
this.tableExposedAPIEmitter.emit('get.selected.rows', payload);
|
||||||
|
const selections = payload.result;
|
||||||
data = data.filter(row => !!selections.find(sel => row[keyField] === sel));
|
data = data.filter(row => !!selections.find(sel => row[keyField] === sel));
|
||||||
}
|
}
|
||||||
const content = transform(data, meta, this._.get, options);
|
const content = transform(data, meta, this._.get, options);
|
||||||
|
|||||||
@@ -26,33 +26,51 @@ const handleDebounce = (func, wait, immediate) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const SearchBar = ({
|
class SearchBar extends React.Component {
|
||||||
delay,
|
constructor(props) {
|
||||||
onSearch,
|
super(props);
|
||||||
className,
|
this.state = {
|
||||||
style,
|
value: props.searchText
|
||||||
placeholder,
|
};
|
||||||
searchText,
|
}
|
||||||
...rest
|
|
||||||
}) => {
|
|
||||||
let input;
|
|
||||||
const debounceCallback = handleDebounce(() => {
|
|
||||||
onSearch(input.value);
|
|
||||||
}, delay);
|
|
||||||
|
|
||||||
return (
|
componentWillReceiveProps(nextProps) {
|
||||||
<input
|
this.setState({ value: nextProps.searchText });
|
||||||
ref={ n => input = n }
|
}
|
||||||
type="text"
|
|
||||||
style={ style }
|
onChangeValue = (e) => {
|
||||||
onKeyUp={ () => debounceCallback() }
|
this.setState({ value: e.target.value });
|
||||||
className={ `form-control ${className}` }
|
}
|
||||||
defaultValue={ searchText }
|
|
||||||
placeholder={ placeholder || SearchBar.defaultProps.placeholder }
|
onKeyup = () => {
|
||||||
{ ...rest }
|
const { delay, onSearch } = this.props;
|
||||||
/>
|
const debounceCallback = handleDebounce(() => {
|
||||||
);
|
onSearch(this.input.value);
|
||||||
};
|
}, delay);
|
||||||
|
debounceCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
placeholder
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
ref={ n => this.input = n }
|
||||||
|
type="text"
|
||||||
|
style={ style }
|
||||||
|
onKeyUp={ () => this.onKeyup() }
|
||||||
|
onChange={ this.onChangeValue }
|
||||||
|
className={ `form-control ${className}` }
|
||||||
|
value={ this.state.value }
|
||||||
|
placeholder={ placeholder || SearchBar.defaultProps.placeholder }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SearchBar.propTypes = {
|
SearchBar.propTypes = {
|
||||||
onSearch: PropTypes.func.isRequired,
|
onSearch: PropTypes.func.isRequired,
|
||||||
|
|||||||
20
packages/react-bootstrap-table2-toolkit/src/search/clear-button.js
vendored
Normal file
20
packages/react-bootstrap-table2-toolkit/src/search/clear-button.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const ClearButton = ({
|
||||||
|
onClear,
|
||||||
|
text
|
||||||
|
}) => (
|
||||||
|
<button className="btn btn-default" onClick={ onClear }>{ text }</button>
|
||||||
|
);
|
||||||
|
|
||||||
|
ClearButton.propTypes = {
|
||||||
|
onClear: PropTypes.func.isRequired,
|
||||||
|
text: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
ClearButton.defaultProps = {
|
||||||
|
text: 'Clear'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClearButton;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
/* eslint react/prop-types: 0 */
|
/* eslint react/prop-types: 0 */
|
||||||
/* eslint react/require-default-props: 0 */
|
/* eslint react/require-default-props: 0 */
|
||||||
/* eslint no-continue: 0 */
|
/* eslint no-continue: 0 */
|
||||||
|
/* eslint no-lonely-if: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
@@ -17,36 +18,48 @@ export default (options = {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
columns: PropTypes.array.isRequired,
|
columns: PropTypes.array.isRequired,
|
||||||
searchText: PropTypes.string
|
searchText: PropTypes.string,
|
||||||
|
dataChangeListener: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.performRemoteSearch = props.searchText !== '';
|
let initialData = props.data;
|
||||||
|
if (isRemoteSearch() && this.props.searchText !== '') {
|
||||||
|
handleRemoteSearchChange(this.props.searchText);
|
||||||
|
} else {
|
||||||
|
initialData = this.search(props.searchText.toLowerCase());
|
||||||
|
this.triggerListener(initialData);
|
||||||
|
}
|
||||||
|
this.state = { data: initialData };
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (isRemoteSearch()) {
|
if (nextProps.searchText !== this.props.searchText) {
|
||||||
if (nextProps.searchText !== this.props.searchText) {
|
if (isRemoteSearch()) {
|
||||||
this.performRemoteSearch = true;
|
handleRemoteSearchChange(nextProps.searchText);
|
||||||
} else {
|
} else {
|
||||||
this.performRemoteSearch = false;
|
const result = this.search(nextProps.searchText.toLowerCase());
|
||||||
|
this.triggerListener(result);
|
||||||
|
this.setState({
|
||||||
|
data: result
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isRemoteSearch()) {
|
||||||
|
this.setState({ data: nextProps.data });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
search() {
|
triggerListener(result) {
|
||||||
const { data, columns } = this.props;
|
if (this.props.dataChangeListener) {
|
||||||
let { searchText } = this.props;
|
this.props.dataChangeListener.emit('filterChanged', result.length);
|
||||||
|
|
||||||
if (isRemoteSearch()) {
|
|
||||||
if (this.performRemoteSearch) {
|
|
||||||
handleRemoteSearchChange(searchText);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
searchText = searchText.toLowerCase();
|
search(searchText) {
|
||||||
|
const { data, columns } = this.props;
|
||||||
return data.filter((row, ridx) => {
|
return data.filter((row, ridx) => {
|
||||||
for (let cidx = 0; cidx < columns.length; cidx += 1) {
|
for (let cidx = 0; cidx < columns.length; cidx += 1) {
|
||||||
const column = columns[cidx];
|
const column = columns[cidx];
|
||||||
@@ -69,9 +82,8 @@ export default (options = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const data = this.search();
|
|
||||||
return (
|
return (
|
||||||
<SearchContext.Provider value={ { data } }>
|
<SearchContext.Provider value={ { data: this.state.data } }>
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</SearchContext.Provider>
|
</SearchContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
import SearchBar from './SearchBar';
|
import SearchBar from './SearchBar';
|
||||||
|
import ClearSearchButton from './clear-button';
|
||||||
|
|
||||||
export default { SearchBar };
|
export default { SearchBar, ClearSearchButton };
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import Operation from './src/op';
|
|||||||
|
|
||||||
export default Base =>
|
export default Base =>
|
||||||
class StatelessOperation extends Operation.csvOperation(Base) {
|
class StatelessOperation extends Operation.csvOperation(Base) {
|
||||||
registerExposedAPI = (...exposedFuncs) => {
|
registerExposedAPI = (tableExposedAPIEmitter) => {
|
||||||
exposedFuncs.forEach((func) => {
|
this.tableExposedAPIEmitter = tableExposedAPIEmitter;
|
||||||
this[func.name] = func;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table-next",
|
"name": "react-bootstrap-table-next",
|
||||||
"version": "2.0.0",
|
"version": "2.1.1",
|
||||||
"description": "Next generation of react-bootstrap-table",
|
"description": "Next generation of react-bootstrap-table",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
42
packages/react-bootstrap-table2/src/body.js
vendored
42
packages/react-bootstrap-table2/src/body.js
vendored
@@ -15,9 +15,36 @@ import withRowExpansion from './row-expand/row-consumer';
|
|||||||
class Body extends React.Component {
|
class Body extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
if (props.cellEdit.createContext) {
|
const {
|
||||||
this.EditingCell = props.cellEdit.createEditingCell(_, props.cellEdit.options.onStartEdit);
|
keyField,
|
||||||
|
visibleColumnSize,
|
||||||
|
cellEdit,
|
||||||
|
selectRow,
|
||||||
|
expandRow
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
// Construct Editing Cell Component
|
||||||
|
if (cellEdit.createContext) {
|
||||||
|
this.EditingCell = cellEdit.createEditingCell(_, cellEdit.options.onStartEdit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct Row Component
|
||||||
|
let RowComponent = SimpleRow;
|
||||||
|
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||||
|
const expandRowEnabled = !!expandRow.renderer;
|
||||||
|
|
||||||
|
if (expandRowEnabled) {
|
||||||
|
RowComponent = withRowExpansion(RowAggregator, visibleColumnSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectRowEnabled) {
|
||||||
|
RowComponent = withRowSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellEdit.createContext) {
|
||||||
|
RowComponent = cellEdit.withRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
||||||
|
}
|
||||||
|
this.RowComponent = RowComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -46,21 +73,12 @@ class Body extends React.Component {
|
|||||||
}
|
}
|
||||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||||
} else {
|
} else {
|
||||||
let RowComponent = SimpleRow;
|
|
||||||
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||||
const expandRowEnabled = !!expandRow.renderer;
|
const expandRowEnabled = !!expandRow.renderer;
|
||||||
|
|
||||||
const additionalRowProps = {};
|
const additionalRowProps = {};
|
||||||
if (expandRowEnabled) {
|
|
||||||
RowComponent = withRowExpansion(RowAggregator, visibleColumnSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectRowEnabled) {
|
|
||||||
RowComponent = withRowSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellEdit.createContext) {
|
if (cellEdit.createContext) {
|
||||||
RowComponent = cellEdit.withRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
|
||||||
additionalRowProps.EditingCellComponent = this.EditingCell;
|
additionalRowProps.EditingCellComponent = this.EditingCell;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +106,7 @@ class Body extends React.Component {
|
|||||||
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
||||||
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
||||||
|
|
||||||
return <RowComponent { ...baseRowProps } />;
|
return <this.RowComponent { ...baseRowProps } />;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,20 +7,19 @@ import cs from 'classnames';
|
|||||||
import Header from './header';
|
import Header from './header';
|
||||||
import Caption from './caption';
|
import Caption from './caption';
|
||||||
import Body from './body';
|
import Body from './body';
|
||||||
|
import Footer from './footer';
|
||||||
import PropsBaseResolver from './props-resolver';
|
import PropsBaseResolver from './props-resolver';
|
||||||
import Const from './const';
|
import Const from './const';
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
class BootstrapTable extends PropsBaseResolver(Component) {
|
class BootstrapTable extends PropsBaseResolver(Component) {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.validateProps();
|
this.validateProps();
|
||||||
if (props.registerExposedAPI) {
|
|
||||||
props.registerExposedAPI(this.getData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exposed APIs
|
// Exposed APIs
|
||||||
getData() {
|
getData = () => {
|
||||||
return this.visibleRows();
|
return this.visibleRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +65,11 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
'table-striped': striped,
|
'table-striped': striped,
|
||||||
'table-hover': hover,
|
'table-hover': hover,
|
||||||
'table-bordered': bordered,
|
'table-bordered': bordered,
|
||||||
[(bootstrap4 ? 'table-sm' : 'table-condensed')]: condensed
|
[bootstrap4 ? 'table-sm' : 'table-condensed']: condensed
|
||||||
}, classes);
|
}, classes);
|
||||||
|
|
||||||
|
const hasFooter = _.filter(columns, col => _.has(col, 'footer')).length > 0;
|
||||||
|
|
||||||
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -101,6 +102,13 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
rowClasses={ rowClasses }
|
rowClasses={ rowClasses }
|
||||||
rowEvents={ rowEvents }
|
rowEvents={ rowEvents }
|
||||||
/>
|
/>
|
||||||
|
{hasFooter && (
|
||||||
|
<Footer
|
||||||
|
data={ this.getData() }
|
||||||
|
columns={ columns }
|
||||||
|
className={ this.props.footerClasses }
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -161,12 +169,17 @@ BootstrapTable.propTypes = {
|
|||||||
onlyOneExpanding: PropTypes.bool,
|
onlyOneExpanding: PropTypes.bool,
|
||||||
expandByColumnOnly: PropTypes.bool,
|
expandByColumnOnly: PropTypes.bool,
|
||||||
expandColumnRenderer: PropTypes.func,
|
expandColumnRenderer: PropTypes.func,
|
||||||
expandHeaderColumnRenderer: PropTypes.func
|
expandHeaderColumnRenderer: PropTypes.func,
|
||||||
|
expandColumnPosition: PropTypes.oneOf([
|
||||||
|
Const.INDICATOR_POSITION_LEFT,
|
||||||
|
Const.INDICATOR_POSITION_RIGHT
|
||||||
|
])
|
||||||
}),
|
}),
|
||||||
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||||
rowEvents: PropTypes.object,
|
rowEvents: PropTypes.object,
|
||||||
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
headerClasses: PropTypes.string,
|
headerClasses: PropTypes.string,
|
||||||
|
footerClasses: PropTypes.string,
|
||||||
defaultSorted: PropTypes.arrayOf(PropTypes.shape({
|
defaultSorted: PropTypes.arrayOf(PropTypes.shape({
|
||||||
dataField: PropTypes.string.isRequired,
|
dataField: PropTypes.string.isRequired,
|
||||||
order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired
|
order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired
|
||||||
|
|||||||
4
packages/react-bootstrap-table2/src/const.js
vendored
4
packages/react-bootstrap-table2/src/const.js
vendored
@@ -6,5 +6,7 @@ export default {
|
|||||||
ROW_SELECT_DISABLED: 'ROW_SELECT_DISABLED',
|
ROW_SELECT_DISABLED: 'ROW_SELECT_DISABLED',
|
||||||
CHECKBOX_STATUS_CHECKED: 'checked',
|
CHECKBOX_STATUS_CHECKED: 'checked',
|
||||||
CHECKBOX_STATUS_INDETERMINATE: 'indeterminate',
|
CHECKBOX_STATUS_INDETERMINATE: 'indeterminate',
|
||||||
CHECKBOX_STATUS_UNCHECKED: 'unchecked'
|
CHECKBOX_STATUS_UNCHECKED: 'unchecked',
|
||||||
|
INDICATOR_POSITION_LEFT: 'left',
|
||||||
|
INDICATOR_POSITION_RIGHT: 'right'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
/* eslint no-return-assign: 0 */
|
/* eslint no-return-assign: 0 */
|
||||||
|
/* eslint no-param-reassign: 0 */
|
||||||
/* eslint class-methods-use-this: 0 */
|
/* eslint class-methods-use-this: 0 */
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import EventEmitter from 'events';
|
||||||
import _ from '../utils';
|
import _ from '../utils';
|
||||||
import createDataContext from './data-context';
|
import createDataContext from './data-context';
|
||||||
import createSortContext from './sort-context';
|
import createSortContext from './sort-context';
|
||||||
@@ -16,6 +18,13 @@ const withContext = Base =>
|
|||||||
super(props);
|
super(props);
|
||||||
this.DataContext = createDataContext();
|
this.DataContext = createDataContext();
|
||||||
|
|
||||||
|
if (props.registerExposedAPI) {
|
||||||
|
const exposedAPIEmitter = new EventEmitter();
|
||||||
|
exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData());
|
||||||
|
exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected());
|
||||||
|
props.registerExposedAPI(exposedAPIEmitter);
|
||||||
|
}
|
||||||
|
|
||||||
if (props.columns.filter(col => col.sort).length > 0) {
|
if (props.columns.filter(col => col.sort).length > 0) {
|
||||||
this.SortContext = createSortContext(
|
this.SortContext = createSortContext(
|
||||||
dataOperator, this.isRemoteSort, this.handleRemoteSortChange);
|
dataOperator, this.isRemoteSort, this.handleRemoteSortChange);
|
||||||
@@ -208,6 +217,7 @@ const withContext = Base =>
|
|||||||
ref={ n => this.searchContext = n }
|
ref={ n => this.searchContext = n }
|
||||||
data={ rootProps.getData(filterProps) }
|
data={ rootProps.getData(filterProps) }
|
||||||
searchText={ this.props.search.searchText }
|
searchText={ this.props.search.searchText }
|
||||||
|
dataChangeListener={ this.props.dataChangeListener }
|
||||||
>
|
>
|
||||||
<this.SearchContext.Consumer>
|
<this.SearchContext.Consumer>
|
||||||
{
|
{
|
||||||
@@ -228,6 +238,7 @@ const withContext = Base =>
|
|||||||
{ ...baseProps }
|
{ ...baseProps }
|
||||||
ref={ n => this.filterContext = n }
|
ref={ n => this.filterContext = n }
|
||||||
data={ rootProps.getData() }
|
data={ rootProps.getData() }
|
||||||
|
dataChangeListener={ this.props.dataChangeListener }
|
||||||
>
|
>
|
||||||
<this.FilterContext.Consumer>
|
<this.FilterContext.Consumer>
|
||||||
{
|
{
|
||||||
@@ -255,9 +266,8 @@ const withContext = Base =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { keyField, columns, bootstrap4, registerExposedAPI } = this.props;
|
const { keyField, columns, bootstrap4 } = this.props;
|
||||||
const baseProps = { keyField, columns };
|
const baseProps = { keyField, columns };
|
||||||
if (registerExposedAPI) baseProps.registerExposedAPI = registerExposedAPI;
|
|
||||||
|
|
||||||
let base = this.renderBase();
|
let base = this.renderBase();
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,6 @@ class SelectionProvider extends React.Component {
|
|||||||
keyField: PropTypes.string.isRequired
|
keyField: PropTypes.string.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
if (props.registerExposedAPI) {
|
|
||||||
const getSelected = () => this.getSelected();
|
|
||||||
props.registerExposedAPI(getSelected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state = { selected: this.props.selectRow.selected || [] };
|
state = { selected: this.props.selectRow.selected || [] };
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
|
|||||||
64
packages/react-bootstrap-table2/src/footer-cell.js
vendored
Normal file
64
packages/react-bootstrap-table2/src/footer-cell.js
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import cs from 'classnames';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
|
const FooterCell = (props) => {
|
||||||
|
const { index, column, columnData } = props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
footer,
|
||||||
|
footerTitle,
|
||||||
|
footerAlign,
|
||||||
|
footerFormatter,
|
||||||
|
footerEvents,
|
||||||
|
footerClasses,
|
||||||
|
footerStyle,
|
||||||
|
footerAttrs
|
||||||
|
} = column;
|
||||||
|
|
||||||
|
const cellAttrs = {
|
||||||
|
...(_.isFunction(footerAttrs) ? footerAttrs(column, index) : footerAttrs),
|
||||||
|
...footerEvents
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = '';
|
||||||
|
if (_.isString(footer)) {
|
||||||
|
text = footer;
|
||||||
|
} else if (_.isFunction(footer)) {
|
||||||
|
text = footer(columnData, column, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cellStyle = {};
|
||||||
|
const cellClasses = _.isFunction(footerClasses) ? footerClasses(column, index) : footerClasses;
|
||||||
|
|
||||||
|
if (footerStyle) {
|
||||||
|
cellStyle = _.isFunction(footerStyle) ? footerStyle(column, index) : footerStyle;
|
||||||
|
cellStyle = cellStyle ? { ...cellStyle } : cellStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footerTitle) {
|
||||||
|
cellAttrs.title = _.isFunction(footerTitle) ? footerTitle(column, index) : text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footerAlign) {
|
||||||
|
cellStyle.textAlign = _.isFunction(footerAlign) ? footerAlign(column, index) : footerAlign;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellClasses) cellAttrs.className = cs(cellAttrs.className, cellClasses);
|
||||||
|
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||||
|
|
||||||
|
const children = footerFormatter ? footerFormatter(column, index) : text;
|
||||||
|
|
||||||
|
return React.createElement('th', cellAttrs, children);
|
||||||
|
};
|
||||||
|
|
||||||
|
FooterCell.propTypes = {
|
||||||
|
columnData: PropTypes.array,
|
||||||
|
index: PropTypes.number,
|
||||||
|
column: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FooterCell;
|
||||||
41
packages/react-bootstrap-table2/src/footer.js
vendored
Normal file
41
packages/react-bootstrap-table2/src/footer.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import FooterCell from './footer-cell';
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
|
const Footer = (props) => {
|
||||||
|
const { data, className, columns } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tfoot>
|
||||||
|
<tr className={ className }>
|
||||||
|
{columns.map((column, i) => {
|
||||||
|
if (column.footer === undefined || column.footer === null || column.hidden) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnData = _.pluck(data, column.dataField);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FooterCell
|
||||||
|
index={ i }
|
||||||
|
key={ column.dataField }
|
||||||
|
column={ column }
|
||||||
|
columnData={ columnData }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Footer.propTypes = {
|
||||||
|
data: PropTypes.array,
|
||||||
|
className: PropTypes.string,
|
||||||
|
columns: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
68
packages/react-bootstrap-table2/src/header.js
vendored
68
packages/react-bootstrap-table2/src/header.js
vendored
@@ -7,6 +7,7 @@ import SelectionHeaderCell from './row-selection/selection-header-cell';
|
|||||||
import ExpandHeaderCell from './row-expand/expand-header-cell';
|
import ExpandHeaderCell from './row-expand/expand-header-cell';
|
||||||
import withHeaderSelection from './row-selection/selection-header-cell-consumer';
|
import withHeaderSelection from './row-selection/selection-header-cell-consumer';
|
||||||
import withHeaderExpansion from './row-expand/expand-header-cell-consumer';
|
import withHeaderExpansion from './row-expand/expand-header-cell-consumer';
|
||||||
|
import Const from './const';
|
||||||
|
|
||||||
const Header = (props) => {
|
const Header = (props) => {
|
||||||
const {
|
const {
|
||||||
@@ -32,36 +33,49 @@ const Header = (props) => {
|
|||||||
SelectionHeaderCellComp = withHeaderSelection(SelectionHeaderCell);
|
SelectionHeaderCellComp = withHeaderSelection(SelectionHeaderCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isRenderExpandColumnInLeft = (
|
||||||
|
expandColumnPosition = Const.INDICATOR_POSITION_LEFT
|
||||||
|
) => expandColumnPosition === Const.INDICATOR_POSITION_LEFT;
|
||||||
|
|
||||||
|
const childrens = [
|
||||||
|
columns.map((column, i) => {
|
||||||
|
if (!column.hidden) {
|
||||||
|
const currSort = column.dataField === sortField;
|
||||||
|
const isLastSorting = column.dataField === sortField;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HeaderCell
|
||||||
|
index={ i }
|
||||||
|
key={ column.dataField }
|
||||||
|
column={ column }
|
||||||
|
onSort={ onSort }
|
||||||
|
sorting={ currSort }
|
||||||
|
onFilter={ onFilter }
|
||||||
|
onExternalFilter={ onExternalFilter }
|
||||||
|
sortOrder={ sortOrder }
|
||||||
|
isLastSorting={ isLastSorting }
|
||||||
|
/>);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!selectRow.hideSelectColumn) {
|
||||||
|
childrens.unshift(<SelectionHeaderCellComp key="selection" />);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expandRow.showExpandColumn) {
|
||||||
|
if (isRenderExpandColumnInLeft(expandRow.expandColumnPosition)) {
|
||||||
|
childrens.unshift(<ExpansionHeaderCellComp key="expansion" />);
|
||||||
|
} else {
|
||||||
|
childrens.push(<ExpansionHeaderCellComp key="expansion" />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<thead>
|
<thead>
|
||||||
<tr className={ className }>
|
<tr className={ className }>
|
||||||
<ExpansionHeaderCellComp />
|
{ childrens }
|
||||||
{
|
|
||||||
!selectRow.hideSelectColumn ?
|
|
||||||
<SelectionHeaderCellComp /> : null
|
|
||||||
}
|
|
||||||
{
|
|
||||||
columns.map((column, i) => {
|
|
||||||
if (!column.hidden) {
|
|
||||||
const currSort = column.dataField === sortField;
|
|
||||||
const isLastSorting = column.dataField === sortField;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<HeaderCell
|
|
||||||
index={ i }
|
|
||||||
key={ column.dataField }
|
|
||||||
column={ column }
|
|
||||||
onSort={ onSort }
|
|
||||||
sorting={ currSort }
|
|
||||||
onFilter={ onFilter }
|
|
||||||
onExternalFilter={ onExternalFilter }
|
|
||||||
sortOrder={ sortOrder }
|
|
||||||
isLastSorting={ isLastSorting }
|
|
||||||
/>);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint class-methods-use-this: 0 */
|
||||||
/* eslint react/prop-types: 0 */
|
/* eslint react/prop-types: 0 */
|
||||||
/* eslint no-plusplus: 0 */
|
/* eslint no-plusplus: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@@ -8,6 +9,7 @@ import SelectionCell from '../row-selection/selection-cell';
|
|||||||
import shouldUpdater from './should-updater';
|
import shouldUpdater from './should-updater';
|
||||||
import eventDelegater from './event-delegater';
|
import eventDelegater from './event-delegater';
|
||||||
import RowPureContent from './row-pure-content';
|
import RowPureContent from './row-pure-content';
|
||||||
|
import Const from '../const';
|
||||||
|
|
||||||
export default class RowAggregator extends shouldUpdater(eventDelegater(React.Component)) {
|
export default class RowAggregator extends shouldUpdater(eventDelegater(React.Component)) {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -43,6 +45,12 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
|
|||||||
return this.shouldUpdateRowContent;
|
return this.shouldUpdateRowContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isRenderExpandColumnInLeft(
|
||||||
|
expandColumnPosition = Const.INDICATOR_POSITION_LEFT
|
||||||
|
) {
|
||||||
|
return expandColumnPosition === Const.INDICATOR_POSITION_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
row,
|
row,
|
||||||
@@ -64,7 +72,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
const key = _.get(row, keyField);
|
const key = _.get(row, keyField);
|
||||||
const { hideSelectColumn, clickToSelect } = selectRow;
|
const { hideSelectColumn, clickToSelect } = selectRow;
|
||||||
const { showExpandColumn } = expandRow;
|
const { showExpandColumn, expandColumnPosition } = expandRow;
|
||||||
|
|
||||||
const newAttrs = this.delegate({ ...attrs });
|
const newAttrs = this.delegate({ ...attrs });
|
||||||
if (clickToSelect || !!expandRow.renderer) {
|
if (clickToSelect || !!expandRow.renderer) {
|
||||||
@@ -73,47 +81,59 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
|
|||||||
|
|
||||||
let tabIndexStart = (rowIndex * visibleColumnSize) + 1;
|
let tabIndexStart = (rowIndex * visibleColumnSize) + 1;
|
||||||
|
|
||||||
|
const childrens = [(
|
||||||
|
<RowPureContent
|
||||||
|
key="row"
|
||||||
|
row={ row }
|
||||||
|
columns={ columns }
|
||||||
|
keyField={ keyField }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
shouldUpdate={ this.shouldUpdateRowContent }
|
||||||
|
tabIndexStart={ tabIndexCell ? tabIndexStart : -1 }
|
||||||
|
{ ...rest }
|
||||||
|
/>
|
||||||
|
)];
|
||||||
|
|
||||||
|
if (!hideSelectColumn) {
|
||||||
|
childrens.unshift((
|
||||||
|
<SelectionCell
|
||||||
|
{ ...selectRow }
|
||||||
|
key="selection-cell"
|
||||||
|
rowKey={ key }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
selected={ selected }
|
||||||
|
disabled={ !selectable }
|
||||||
|
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showExpandColumn) {
|
||||||
|
const expandCell = (
|
||||||
|
<ExpandCell
|
||||||
|
{ ...expandRow }
|
||||||
|
key="expand-cell"
|
||||||
|
rowKey={ key }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
expanded={ expanded }
|
||||||
|
expandable={ expandable }
|
||||||
|
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
if (this.isRenderExpandColumnInLeft(expandColumnPosition)) {
|
||||||
|
childrens.unshift(expandCell);
|
||||||
|
} else {
|
||||||
|
childrens.push(expandCell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
style={ style }
|
style={ style }
|
||||||
className={ className }
|
className={ className }
|
||||||
{ ...newAttrs }
|
{ ...newAttrs }
|
||||||
>
|
>
|
||||||
{
|
{ childrens }
|
||||||
showExpandColumn ? (
|
|
||||||
<ExpandCell
|
|
||||||
{ ...expandRow }
|
|
||||||
rowKey={ key }
|
|
||||||
rowIndex={ rowIndex }
|
|
||||||
expanded={ expanded }
|
|
||||||
expandable={ expandable }
|
|
||||||
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
{
|
|
||||||
!hideSelectColumn
|
|
||||||
? (
|
|
||||||
<SelectionCell
|
|
||||||
{ ...selectRow }
|
|
||||||
rowKey={ key }
|
|
||||||
rowIndex={ rowIndex }
|
|
||||||
selected={ selected }
|
|
||||||
disabled={ !selectable }
|
|
||||||
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
<RowPureContent
|
|
||||||
row={ row }
|
|
||||||
columns={ columns }
|
|
||||||
keyField={ keyField }
|
|
||||||
rowIndex={ rowIndex }
|
|
||||||
shouldUpdate={ this.shouldUpdateRowContent }
|
|
||||||
tabIndexStart={ tabIndexCell ? tabIndexStart : -1 }
|
|
||||||
{ ...rest }
|
|
||||||
/>
|
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,19 @@ export default ExtendBase =>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only use for simple-row
|
||||||
|
shouldUpdateByColumnsForSimpleCheck(nextProps) {
|
||||||
|
if (this.props.columns.length !== nextProps.columns.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this.props.columns.length; i += 1) {
|
||||||
|
if (this.props.columns[i].hidden !== nextProps.columns[i].hidden) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
shouldUpdatedByNormalProps(nextProps) {
|
shouldUpdatedByNormalProps(nextProps) {
|
||||||
const shouldUpdate =
|
const shouldUpdate =
|
||||||
this.props.rowIndex !== nextProps.rowIndex ||
|
this.props.rowIndex !== nextProps.rowIndex ||
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ class SimpleRow extends shouldUpdater(eventDelegater(Component)) {
|
|||||||
|
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
this.shouldUpdateRowContent = false;
|
this.shouldUpdateRowContent = false;
|
||||||
this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps);
|
this.shouldUpdateRowContent =
|
||||||
|
this.shouldUpdateChild(nextProps) || this.shouldUpdateByColumnsForSimpleCheck(nextProps);
|
||||||
if (this.shouldUpdateRowContent) return true;
|
if (this.shouldUpdateRowContent) return true;
|
||||||
|
|
||||||
return this.shouldUpdatedBySelfProps(nextProps);
|
return this.shouldUpdatedBySelfProps(nextProps);
|
||||||
|
|||||||
@@ -60,26 +60,6 @@ describe('BootstrapTable', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when props.registerExposedAPI is defined', () => {
|
|
||||||
const registerExposedAPI = jest.fn();
|
|
||||||
beforeEach(() => {
|
|
||||||
registerExposedAPI.mockClear();
|
|
||||||
wrapper = shallow(
|
|
||||||
<BootstrapTable
|
|
||||||
keyField="id"
|
|
||||||
columns={ columns }
|
|
||||||
data={ data }
|
|
||||||
registerExposedAPI={ registerExposedAPI }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call props.registerExposedAPI correctly', () => {
|
|
||||||
expect(registerExposedAPI).toHaveBeenCalledTimes(1);
|
|
||||||
expect(registerExposedAPI.mock.calls[0][0].name).toEqual('getData');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when props.classes was defined', () => {
|
describe('when props.classes was defined', () => {
|
||||||
const classes = 'foo';
|
const classes = 'foo';
|
||||||
|
|
||||||
|
|||||||
@@ -225,4 +225,31 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().PaginationContext).toBeDefined();
|
expect(wrapper.instance().PaginationContext).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('if registerExposedAPI props is defined', () => {
|
||||||
|
const registerExposedAPI = jest.fn();
|
||||||
|
beforeEach(() => {
|
||||||
|
const PaginationContext = React.createContext();
|
||||||
|
const paginator = {
|
||||||
|
createContext: jest.fn().mockReturnValue({
|
||||||
|
Provider: PaginationContext.Provider,
|
||||||
|
Consumer: PaginationContext.Consumer
|
||||||
|
})
|
||||||
|
};
|
||||||
|
wrapper = shallow(
|
||||||
|
<BootstrapTable
|
||||||
|
keyField={ keyField }
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
pagination={ paginator }
|
||||||
|
registerExposedAPI={ registerExposedAPI }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call props.registerExposedAPI correctly', () => {
|
||||||
|
expect(registerExposedAPI).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
61
packages/react-bootstrap-table2/test/footer.test.js
Normal file
61
packages/react-bootstrap-table2/test/footer.test.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow, mount } from 'enzyme';
|
||||||
|
|
||||||
|
import Footer from '../src/footer';
|
||||||
|
import FooterCell from '../src/footer-cell';
|
||||||
|
|
||||||
|
describe('Footer', () => {
|
||||||
|
let wrapper;
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID',
|
||||||
|
footer: 'Footer 1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Name',
|
||||||
|
footer: (columnData, column) => 'Footer 2'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'A'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: 'B'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const keyField = 'id';
|
||||||
|
|
||||||
|
describe('simplest footer', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<Footer data={ data } columns={ columns } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('tr').length).toBe(1);
|
||||||
|
expect(wrapper.find(FooterCell).length).toBe(columns.length);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('className prop is exists', () => {
|
||||||
|
const className = 'test-class';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<Footer data={ data } columns={ columns } className={ className } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find(`.${className}`).length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -254,5 +254,33 @@ describe('Header', () => {
|
|||||||
expect(wrapper.find(ExpandHeaderCell).length).toBe(1);
|
expect(wrapper.find(ExpandHeaderCell).length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('if props.expandRow.showExpandColumn is true but props.expandRow.expandColumnPosition is "right"', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const expandRow = {
|
||||||
|
renderer: jest.fn(),
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandColumnPosition: Const.INDICATOR_POSITION_RIGHT
|
||||||
|
};
|
||||||
|
wrapper = mount(
|
||||||
|
<ExpansionContext.Provider
|
||||||
|
data={ data }
|
||||||
|
keyField={ keyField }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
>
|
||||||
|
<Header
|
||||||
|
{ ...mockHeaderResolvedProps }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
</ExpansionContext.Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render expansion column correctly', () => {
|
||||||
|
const header = wrapper.find(Header).children();
|
||||||
|
expect(header.children().children().last().find(ExpandHeaderCell)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import bindExpansion from '../../src/row-expand/row-consumer';
|
|||||||
import ExpandCell from '../../src/row-expand/expand-cell';
|
import ExpandCell from '../../src/row-expand/expand-cell';
|
||||||
import SelectionCell from '../../src/row-selection/selection-cell';
|
import SelectionCell from '../../src/row-selection/selection-cell';
|
||||||
import RowAggregator from '../../src/row/aggregate-row';
|
import RowAggregator from '../../src/row/aggregate-row';
|
||||||
|
import Const from '../../src/const';
|
||||||
|
|
||||||
describe('Row Aggregator', () => {
|
describe('Row Aggregator', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
@@ -157,6 +158,27 @@ describe('Row Aggregator', () => {
|
|||||||
expect(expandCell.props().expanded).toEqual(rowAggregator.props().expanded);
|
expect(expandCell.props().expanded).toEqual(rowAggregator.props().expanded);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('if props.expandRow.showExpandColumn is true but props.expandRow.expandColumnPosition is "right"', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const expandRow = {
|
||||||
|
renderer: jest.fn(),
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandColumnPosition: Const.INDICATOR_POSITION_RIGHT
|
||||||
|
};
|
||||||
|
wrapper = mount(
|
||||||
|
<ExpansionContext.Provider data={ data } keyField={ keyField } expandRow={ expandRow }>
|
||||||
|
<RowAggregatorWithExpansion { ...getBaseProps() } />
|
||||||
|
</ExpansionContext.Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render expansion column correctly', () => {
|
||||||
|
rowAggregator = wrapper.find(RowAggregator);
|
||||||
|
expect(rowAggregator).toHaveLength(1);
|
||||||
|
expect(rowAggregator.children().children().last().type()).toEqual(ExpandCell);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('createClickEventHandler', () => {
|
describe('createClickEventHandler', () => {
|
||||||
|
|||||||
@@ -104,6 +104,50 @@ describe('Row shouldUpdater', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('shouldUpdateByColumnsForSimpleCheck', () => {
|
||||||
|
describe('when nextProps.columns.length is not eq props.columns.length', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
columns: [{ dataField: 'price', text: 'Price' }]
|
||||||
|
};
|
||||||
|
wrapper = shallow(<DummyComponent { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true', () => {
|
||||||
|
nextProps = { ...props, columns: [...props.columns, { dataField: 'name', text: 'Name' }] };
|
||||||
|
expect(wrapper.instance().shouldUpdateByColumnsForSimpleCheck(nextProps)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when any nextProps.columns.hidden is change', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
columns: [{ dataField: 'price', text: 'Price' }]
|
||||||
|
};
|
||||||
|
wrapper = shallow(<DummyComponent { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true', () => {
|
||||||
|
nextProps = { ...props, columns: [{ dataField: 'price', text: 'Price', hidden: true }] };
|
||||||
|
expect(wrapper.instance().shouldUpdateByColumnsForSimpleCheck(nextProps)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if any nextProps.columns.hidden is not change and column length is same', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
columns: [{ dataField: 'price', text: 'Price' }]
|
||||||
|
};
|
||||||
|
wrapper = shallow(<DummyComponent { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false', () => {
|
||||||
|
nextProps = { ...props, columns: [...props.columns] };
|
||||||
|
expect(wrapper.instance().shouldUpdateByColumnsForSimpleCheck(nextProps)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('shouldUpdatedByNormalProps', () => {
|
describe('shouldUpdatedByNormalProps', () => {
|
||||||
describe('when nextProps.rowIndex is not eq props.rowIndex', () => {
|
describe('when nextProps.rowIndex is not eq props.rowIndex', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user