mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 13:40:07 +00:00
Compare commits
81 Commits
react-boot
...
react-boot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
497bf44192 | ||
|
|
fcefcf8c84 | ||
|
|
04e3af0bbb | ||
|
|
9f47fa009c | ||
|
|
0edf9c8891 | ||
|
|
df5024892c | ||
|
|
4448c3f28c | ||
|
|
196ae33295 | ||
|
|
7f1b7a6c97 | ||
|
|
a6ccafcc75 | ||
|
|
06d87299a3 | ||
|
|
5891ec1b93 | ||
|
|
c5d9e04c2c | ||
|
|
dba3da28c1 | ||
|
|
a0e09cd804 | ||
|
|
d0e70f7246 | ||
|
|
b93c683f17 | ||
|
|
f80e1ea66c | ||
|
|
7642bfa1a3 | ||
|
|
8f304a849f | ||
|
|
956f1cef4d | ||
|
|
c45deee590 | ||
|
|
2aab4301dd | ||
|
|
43aa280761 | ||
|
|
3af30a0265 | ||
|
|
4b8b8b261e | ||
|
|
e44782f222 | ||
|
|
921e8c7ecc | ||
|
|
a3b3ce0dc4 | ||
|
|
e9f08d278d | ||
|
|
b4973c826c | ||
|
|
33c026c7e2 | ||
|
|
6cac7f6dc8 | ||
|
|
da5b93c3cf | ||
|
|
3ffccce1fe | ||
|
|
09f21e8130 | ||
|
|
bf0c5c43a2 | ||
|
|
c01f45a719 | ||
|
|
d26c13b9be | ||
|
|
d84fd5c801 | ||
|
|
8e940112f5 | ||
|
|
6070d150a9 | ||
|
|
dab6f1b206 | ||
|
|
2a497194e7 | ||
|
|
f5f17897fd | ||
|
|
2932b8a1b8 | ||
|
|
93103e5ca0 | ||
|
|
a7c2a49182 | ||
|
|
cd27ff98ff | ||
|
|
4d815894e6 | ||
|
|
d9ff201373 | ||
|
|
8e142de332 | ||
|
|
322605f14e | ||
|
|
3156e01dd6 | ||
|
|
052284a163 | ||
|
|
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 |
@@ -69,7 +69,7 @@ const cellEdit: {
|
|||||||
// omit...
|
// omit...
|
||||||
beforeSaveCell(oldValue, newValue, row, column, done) {
|
beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (confirm('Do you want to accep this change?')) {
|
if (confirm('Do you want to accept this change?')) {
|
||||||
done(); // contine to save the changes
|
done(); // contine to save the changes
|
||||||
} else {
|
} else {
|
||||||
done(false); // reject the changes
|
done(false); // reject the changes
|
||||||
|
|||||||
168
docs/columns.md
168
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)
|
||||||
@@ -156,7 +164,7 @@ Enable the column sort via a `true` value given.
|
|||||||
```
|
```
|
||||||
|
|
||||||
## <a name='sortCaret'>column.sortCaret - [Function]</a>
|
## <a name='sortCaret'>column.sortCaret - [Function]</a>
|
||||||
Use`column.sortCaret` to custom the sort caret. This callback function accept two arguments: `order` and `column`
|
Use`column.sortCaret` to customize the sort caret. This callback function accept two arguments: `order` and `column`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
@@ -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`.
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ Currently, **I still can't implement all the mainly features in legacy `react-bo
|
|||||||
* [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay)
|
* [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay)
|
||||||
* Overlay/Loading Addons
|
* Overlay/Loading Addons
|
||||||
* [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit)
|
* [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit)
|
||||||
* Table Toolkits, like search, csv etc.
|
* Table Toolkits, like search, csv, column toggle etc.
|
||||||
|
|
||||||
This can help your application with less bundled size and also help `react-bootstrap-table2` have clean design to avoid handling to much logic in kernel module(SRP). Hence, which means you probably need to install above addons when you need specific features.
|
This can help your application with less bundled size and also help `react-bootstrap-table2` have clean design to avoid handling to much logic in kernel module(SRP). Hence, which means you probably need to install above addons when you need specific features.
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Row expand
|
# Row expand
|
||||||
`react-bootstrap-table2` supports the row expand feature. By passing prop `expandRow` to enable this functionality.
|
`react-bootstrap-table2` supports the row expand feature. By passing prop `expandRow` to enable this functionality.
|
||||||
|
|
||||||
> Default is click to expand/collapse a row. In addition, we don't support any way to chagne this mechanism!
|
> Default is click to expand/collapse a row. In addition, we don't support any way to change this mechanism!
|
||||||
|
|
||||||
## Required
|
## Required
|
||||||
* [renderer (**required**)](#renderer)
|
* [renderer (**required**)](#renderer)
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ Provide a callback function which allow you to custom the checkbox/radio box. Th
|
|||||||
```js
|
```js
|
||||||
const selectRow = {
|
const selectRow = {
|
||||||
mode: 'checkbox',
|
mode: 'checkbox',
|
||||||
selectionRenderer: ({ mode, checked, disabled }) => (
|
selectionRenderer: ({ mode, checked, disabled, rowIndex }) => (
|
||||||
// ....
|
// ....
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,7 +89,8 @@
|
|||||||
"jest": {
|
"jest": {
|
||||||
"collectCoverageFrom": [
|
"collectCoverageFrom": [
|
||||||
"packages/*/src/**/*.js",
|
"packages/*/src/**/*.js",
|
||||||
"packages/*/index.js"
|
"packages/*/index.js",
|
||||||
|
"!packages/react-bootstrap-table2-example/**/*.js"
|
||||||
],
|
],
|
||||||
"roots": [
|
"roots": [
|
||||||
"<rootDir>/packages"
|
"<rootDir>/packages"
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ const columns = [
|
|||||||
if (typeof cell !== 'object') {
|
if (typeof cell !== 'object') {
|
||||||
dateObj = new Date(cell);
|
dateObj = new Date(cell);
|
||||||
}
|
}
|
||||||
return `${('0' + dateObj.getDate()).slice(-2)}/${('0' + (dateObj.getMonth() + 1)).slice(-2)}/${dateObj.getFullYear()}`;
|
return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`;
|
||||||
},
|
},
|
||||||
editor: {
|
editor: {
|
||||||
type: Type.DATE
|
type: Type.DATE
|
||||||
@@ -173,16 +173,16 @@ If you feel above predefined editors are not satisfied to your requirement, you
|
|||||||
|
|
||||||
* `editorProps`: Some useful attributes you can use on DOM editor, like class, style etc.
|
* `editorProps`: Some useful attributes you can use on DOM editor, like class, style etc.
|
||||||
* `value`: Current cell value
|
* `value`: Current cell value
|
||||||
* `row`: Current row data
|
* `row`: Current row data
|
||||||
* `column`: Current column definition
|
* `column`: Current column definition
|
||||||
* `rowIndex`: Current row index
|
* `rowIndex`: Current row index
|
||||||
* `columnIndex`: Current column index
|
* `columnIndex`: Current column index
|
||||||
|
|
||||||
> Note when implement a custom React editor component, this component should have a **getValue** function which return current value on editor
|
> Note when implement a custom React editor component, this component should have a **getValue** function which return current value on editor
|
||||||
|
|
||||||
> Note when you want to save value, you can call **editorProps.onUpdate** function
|
> Note when you want to save value, you can call **editorProps.onUpdate** function
|
||||||
|
|
||||||
Following is a short example:
|
Following is a short example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class QualityRanger extends React.Component {
|
class QualityRanger extends React.Component {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-editor",
|
"name": "react-bootstrap-table2-editor",
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"description": "it's the editor addon for react-bootstrap-table2",
|
"description": "it's the editor addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
81
packages/react-bootstrap-table2-example/examples/bootstrap4/column-toggle.js
vendored
Normal file
81
packages/react-bootstrap-table2-example/examples/bootstrap4/column-toggle.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
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, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
90
packages/react-bootstrap-table2-example/examples/bootstrap4/toolkits.js
vendored
Normal file
90
packages/react-bootstrap-table2-example/examples/bootstrap4/toolkits.js
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { Search, CSVExport } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { SearchBar, ClearSearchButton } = Search;
|
||||||
|
const { ExportCSVButton } = CSVExport;
|
||||||
|
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, CSVExport } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { SearchBar, ClearSearchButton } = Search;
|
||||||
|
const { ExportCSVButton } = CSVExport;
|
||||||
|
|
||||||
|
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 }
|
||||||
|
/>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
</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 }
|
||||||
|
/>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -18,6 +18,11 @@ class QualityRanger extends React.Component {
|
|||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
value: 0
|
value: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.range.focus();
|
||||||
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
return parseInt(this.range.value, 10);
|
return parseInt(this.range.value, 10);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const columns = [{
|
|||||||
if (typeof cell !== 'object') {
|
if (typeof cell !== 'object') {
|
||||||
dateObj = new Date(cell);
|
dateObj = new Date(cell);
|
||||||
}
|
}
|
||||||
return `${('0' + dateObj.getDate()).slice(-2)}/${('0' + (dateObj.getMonth() + 1)).slice(-2)}/${dateObj.getFullYear()}`;
|
return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`;
|
||||||
},
|
},
|
||||||
editor: {
|
editor: {
|
||||||
type: Type.DATE
|
type: Type.DATE
|
||||||
@@ -48,7 +48,7 @@ const columns = [{
|
|||||||
if (typeof cell !== 'object') {
|
if (typeof cell !== 'object') {
|
||||||
dateObj = new Date(cell);
|
dateObj = new Date(cell);
|
||||||
}
|
}
|
||||||
return \`$\{('0' + dateObj.getDate()).slice(-2)}/$\{('0' + (dateObj.getMonth() + 1)).slice(-2)}/$\{dateObj.getFullYear()}\`;
|
return \`$\{('0' + dateObj.getUTCDate()).slice(-2)}/$\{('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/$\{dateObj.getUTCFullYear()}\`;
|
||||||
},
|
},
|
||||||
editor: {
|
editor: {
|
||||||
type: Type.DATE
|
type: Type.DATE
|
||||||
|
|||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
135
packages/react-bootstrap-table2-example/examples/column-toggle/custom-toggle-list.js
vendored
Normal file
135
packages/react-bootstrap-table2-example/examples/column-toggle/custom-toggle-list.js
vendored
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columnsdt = [{
|
||||||
|
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 from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const CustomToggleList = ({
|
||||||
|
columns,
|
||||||
|
onColumnToggle,
|
||||||
|
toggles
|
||||||
|
}) => (
|
||||||
|
<div className="btn-group btn-group-toggle btn-group-vertical" data-toggle="buttons">
|
||||||
|
{
|
||||||
|
columns
|
||||||
|
.map(column => ({
|
||||||
|
...column,
|
||||||
|
toggle: toggles[column.dataField]
|
||||||
|
}))
|
||||||
|
.map(column => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
key={ column.dataField }
|
||||||
|
className={ \`btn btn-warning \${column.toggle ? 'active' : ''}\` }
|
||||||
|
data-toggle="button"
|
||||||
|
aria-pressed={ column.toggle ? 'true' : 'false' }
|
||||||
|
onClick={ () => onColumnToggle(column.dataField) }
|
||||||
|
>
|
||||||
|
{ column.text }
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columnsdt }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<CustomToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CustomToggleList = ({
|
||||||
|
columns,
|
||||||
|
onColumnToggle,
|
||||||
|
toggles
|
||||||
|
}) => (
|
||||||
|
<div className="btn-group btn-group-toggle btn-group-vertical" data-toggle="buttons">
|
||||||
|
{
|
||||||
|
columns
|
||||||
|
.map(column => ({
|
||||||
|
...column,
|
||||||
|
toggle: toggles[column.dataField]
|
||||||
|
}))
|
||||||
|
.map(column => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
key={ column.dataField }
|
||||||
|
className={ `btn btn-warning ${column.toggle ? 'active' : ''}` }
|
||||||
|
data-toggle="button"
|
||||||
|
aria-pressed={ column.toggle ? 'true' : 'false' }
|
||||||
|
onClick={ () => onColumnToggle(column.dataField) }
|
||||||
|
>
|
||||||
|
{ column.text }
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columnsdt }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<CustomToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
81
packages/react-bootstrap-table2-example/examples/column-toggle/default-visibility.js
vendored
Normal file
81
packages/react-bootstrap-table2-example/examples/column-toggle/default-visibility.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
hidden: true
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
hidden: true
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
hidden: true
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
hidden: true
|
||||||
|
}];
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable { ...props.baseProps } />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable { ...props.baseProps } />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
81
packages/react-bootstrap-table2-example/examples/column-toggle/index.js
vendored
Normal file
81
packages/react-bootstrap-table2-example/examples/column-toggle/index.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
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, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
91
packages/react-bootstrap-table2-example/examples/column-toggle/styling-toggle-list.js
vendored
Normal file
91
packages/react-bootstrap-table2-example/examples/column-toggle/styling-toggle-list.js
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
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, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const { ToggleList } = ColumnToggle;
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList
|
||||||
|
contextual="success"
|
||||||
|
className="list-custom-class"
|
||||||
|
btnClassName="list-btn-custom-class"
|
||||||
|
{ ...props.columnToggleProps }
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList
|
||||||
|
contextual="success"
|
||||||
|
className="list-custom-class"
|
||||||
|
btnClassName="list-btn-custom-class"
|
||||||
|
{ ...props.columnToggleProps }
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -11,141 +11,13 @@ const products = [
|
|||||||
{ id: 14, name: 'Item 14', price: 14.5, inStock: true }
|
{ id: 14, name: 'Item 14', price: 14.5, inStock: true }
|
||||||
];
|
];
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
dataField: 'id',
|
|
||||||
text: 'Product ID'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'name',
|
|
||||||
text: 'Product Name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'price',
|
|
||||||
text: 'Product Price'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'inStock',
|
|
||||||
text: 'In Stock',
|
|
||||||
formatter: (cellContent, row) => (
|
|
||||||
<div className="checkbox disabled">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" checked={ row.inStock } disabled />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'df1',
|
|
||||||
isDummyField: true,
|
|
||||||
text: 'Action 1',
|
|
||||||
formatter: (cellContent, row) => {
|
|
||||||
if (row.inStock) {
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-success"> Available</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-danger"> Backordered</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'df2',
|
|
||||||
isDummyField: true,
|
|
||||||
text: 'Action 2',
|
|
||||||
formatter: (cellContent, row) => {
|
|
||||||
if (row.inStock) {
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-success"> Available</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-danger"> Backordered</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const sourceCode = `\
|
const sourceCode = `\
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
dataField: 'id',
|
|
||||||
text: 'Product ID'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'name',
|
|
||||||
text: 'Product Name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'price',
|
|
||||||
text: 'Product Price'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'inStock',
|
|
||||||
text: 'In Stock',
|
|
||||||
formatter: (cellContent, row) => (
|
|
||||||
<div className="checkbox disabled">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" checked={ row.inStock } disabled />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'df1',
|
|
||||||
isDummyField: true,
|
|
||||||
text: 'Action 1',
|
|
||||||
formatter: (cellContent, row) => {
|
|
||||||
if (row.inStock) {
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-success"> Available</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-danger"> Backordered</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dataField: 'df2',
|
|
||||||
isDummyField: true,
|
|
||||||
text: 'Action 2',
|
|
||||||
formatter: (cellContent, row) => {
|
|
||||||
if (row.inStock) {
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-success"> Available</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<h5>
|
|
||||||
<span className="label label-danger"> Backordered</span>
|
|
||||||
</h5>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
class ProductList extends React.Component {
|
class ProductList extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { products };
|
this.state = { products, count: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleInStock = () => {
|
toggleInStock = () => {
|
||||||
@@ -163,17 +35,96 @@ class ProductList extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
formatter: (cell, row, rowIndex, extraData) => (
|
||||||
|
<div>
|
||||||
|
<span>ID: {row.id}</span>
|
||||||
|
<br />
|
||||||
|
<span>state: {extraData}</span>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
formatExtraData: this.state.count
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'inStock',
|
||||||
|
text: 'In Stock',
|
||||||
|
formatter: (cellContent, row) => (
|
||||||
|
<div className="checkbox disabled">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" checked={ row.inStock } disabled />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'df1',
|
||||||
|
isDummyField: true,
|
||||||
|
text: 'Action 1',
|
||||||
|
formatter: (cellContent, row) => {
|
||||||
|
if (row.inStock) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-success"> Available</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-danger"> Backordered</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'df2',
|
||||||
|
isDummyField: true,
|
||||||
|
text: 'Action 2',
|
||||||
|
formatter: (cellContent, row) => {
|
||||||
|
if (row.inStock) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-success"> Available</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-danger"> Backordered</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="h2">Products</h1>
|
<h3>Action 1 and Action 2 are dummy column</h3>
|
||||||
|
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
||||||
|
Toggle item 13 stock status
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-success"
|
||||||
|
onClick={ () => this.setState(() => ({ count: this.state.count + 1 })) }
|
||||||
|
>
|
||||||
|
Click me to Increase counter
|
||||||
|
</button>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ this.state.products }
|
data={ this.state.products }
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
/>
|
/>
|
||||||
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
<Code>{ sourceCode }</Code>
|
||||||
Toggle item 13 stock status
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -183,7 +134,7 @@ class ProductList extends React.Component {
|
|||||||
class ProductList extends React.Component {
|
class ProductList extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { products };
|
this.state = { products, count: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleInStock = () => {
|
toggleInStock = () => {
|
||||||
@@ -200,13 +151,95 @@ class ProductList extends React.Component {
|
|||||||
this.setState(curr => ({ ...curr, products: newProducts }));
|
this.setState(curr => ({ ...curr, products: newProducts }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
counter = () => {
|
||||||
|
this.setState(curr => ({ ...curr, count: this.state.count + 1 }));
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
formatter: (cell, row, rowIndex, extraData) => (
|
||||||
|
<div>
|
||||||
|
<span>ID: {row.id}</span>
|
||||||
|
<br />
|
||||||
|
<span>Counter: {extraData}</span>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
formatExtraData: this.state.count
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'inStock',
|
||||||
|
text: 'In Stock',
|
||||||
|
formatter: (cellContent, row) => (
|
||||||
|
<div className="checkbox disabled">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" checked={ row.inStock } disabled />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'df1',
|
||||||
|
isDummyField: true,
|
||||||
|
text: 'Action 1',
|
||||||
|
formatter: (cellContent, row) => {
|
||||||
|
if (row.inStock) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-success"> Available</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-danger"> Backordered</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'df2',
|
||||||
|
isDummyField: true,
|
||||||
|
text: 'Action 2',
|
||||||
|
formatter: (cellContent, row) => {
|
||||||
|
if (row.inStock) {
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-success"> Available</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<h5>
|
||||||
|
<span className="label label-danger"> Backordered</span>
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3>Action 1 and Action 2 are dummy column</h3>
|
<h3>Action 1 and Action 2 are dummy column</h3>
|
||||||
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
||||||
Toggle item 13 stock status
|
Toggle item 13 stock status
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-success"
|
||||||
|
onClick={ this.counter }
|
||||||
|
>
|
||||||
|
Click me to Increase counter
|
||||||
|
</button>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ this.state.products }
|
data={ this.state.products }
|
||||||
|
|||||||
102
packages/react-bootstrap-table2-example/examples/csv/export-only-filtered.js
vendored
Normal file
102
packages/react-bootstrap-table2-example/examples/csv/export-only-filtered.js
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { CSVExport, Search } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { SearchBar } = Search;
|
||||||
|
const { ExportCSVButton } = CSVExport;
|
||||||
|
const products = productsGenerator(150);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { CSVExport, Search } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const { SearchBar } = Search;
|
||||||
|
const { ExportCSVButton } = CSVExport;
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true
|
||||||
|
};
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV={ { onlyExportFiltered: true, exportAll: false } }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
<hr />
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Export all the filtered/searched rows</h3>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV={ { onlyExportFiltered: true, exportAll: false } }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
<hr />
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const ProductList = (props) => {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter({
|
||||||
|
defaultValue: '1'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={ { paddingTop: '20px' } }>
|
||||||
|
<h1 className="h2">Products</h1>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ props.products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DataContainer extends React.Component {
|
||||||
|
state = {
|
||||||
|
products: productsGenerator(3)
|
||||||
|
};
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({
|
||||||
|
products: productsGenerator(14)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={ this.loadData }
|
||||||
|
style={ {
|
||||||
|
fontSize: '20px',
|
||||||
|
position: 'absolute',
|
||||||
|
left: '200px',
|
||||||
|
top: '40px'
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
Load Data
|
||||||
|
</button>
|
||||||
|
<ProductList products={ this.state.products } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/* 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 { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { SearchBar } = Search;
|
||||||
|
const ProductList = (props) => {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={ { paddingTop: '20px' } }>
|
||||||
|
<h1 className="h2">Products</h1>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ props.products }
|
||||||
|
columns={ columns }
|
||||||
|
search={ { defaultSearch: '2101' } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
toolkitprops => (
|
||||||
|
<div>
|
||||||
|
<SearchBar { ...toolkitprops.searchProps } />
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
{ ...toolkitprops.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DataContainer extends React.Component {
|
||||||
|
state = {
|
||||||
|
products: productsGenerator(3)
|
||||||
|
};
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({
|
||||||
|
products: productsGenerator(14)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={ this.loadData }
|
||||||
|
style={ {
|
||||||
|
fontSize: '20px',
|
||||||
|
position: 'absolute',
|
||||||
|
left: '200px',
|
||||||
|
top: '40px'
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
Load Data
|
||||||
|
</button>
|
||||||
|
<ProductList products={ this.state.products } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
68
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js
vendored
Normal file
68
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-filter.js
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const ProductList = (props) => {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={ { paddingTop: '20px' } }>
|
||||||
|
<h1 className="h2">Products</h1>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ props.products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DataContainer extends React.Component {
|
||||||
|
state = {
|
||||||
|
products: []
|
||||||
|
};
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({
|
||||||
|
products: productsGenerator()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={ this.loadData }
|
||||||
|
style={ {
|
||||||
|
fontSize: '20px',
|
||||||
|
position: 'absolute',
|
||||||
|
left: '200px',
|
||||||
|
top: '40px'
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
Load Data
|
||||||
|
</button>
|
||||||
|
<ProductList products={ this.state.products } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const ProductList = (props) => {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter({
|
||||||
|
defaultValue: '6'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
filter: textFilter()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={ { paddingTop: '20px' } }>
|
||||||
|
<h1 className="h2">Products</h1>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ props.products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DataContainer extends React.Component {
|
||||||
|
state = {
|
||||||
|
products: productsGenerator(60)
|
||||||
|
};
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({
|
||||||
|
products: productsGenerator(14)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={ this.loadData }
|
||||||
|
style={ {
|
||||||
|
fontSize: '20px',
|
||||||
|
position: 'absolute',
|
||||||
|
left: '200px',
|
||||||
|
top: '40px'
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
Load Data
|
||||||
|
</button>
|
||||||
|
<ProductList products={ this.state.products } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
80
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js
vendored
Normal file
80
packages/react-bootstrap-table2-example/examples/data/load-data-on-the-fly-with-search.js
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* 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 { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { SearchBar } = Search;
|
||||||
|
const ProductList = (props) => {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={ { paddingTop: '20px' } }>
|
||||||
|
<h1 className="h2">Products</h1>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ props.products }
|
||||||
|
columns={ columns }
|
||||||
|
search
|
||||||
|
>
|
||||||
|
{
|
||||||
|
toolkitprops => (
|
||||||
|
<div>
|
||||||
|
<SearchBar { ...toolkitprops.searchProps } />
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
{ ...toolkitprops.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class DataContainer extends React.Component {
|
||||||
|
state = {
|
||||||
|
products: []
|
||||||
|
};
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({
|
||||||
|
products: productsGenerator()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={ this.loadData }
|
||||||
|
style={ {
|
||||||
|
fontSize: '20px',
|
||||||
|
position: 'absolute',
|
||||||
|
left: '200px',
|
||||||
|
top: '40px'
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
Load Data
|
||||||
|
</button>
|
||||||
|
<ProductList products={ this.state.products } />
|
||||||
|
</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>
|
||||||
|
);
|
||||||
159
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list-with-search.js
vendored
Normal file
159
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list-with-search.js
vendored
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/* 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(40);
|
||||||
|
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 {
|
||||||
|
state = { products }
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({ products: productsGenerator(17) });
|
||||||
|
}
|
||||||
|
|
||||||
|
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: this.state.products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
columns={ columns }
|
||||||
|
data={ this.state.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 >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class Table extends React.Component {
|
||||||
|
state = { products }
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({ products: productsGenerator(17) });
|
||||||
|
}
|
||||||
|
|
||||||
|
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: this.state.products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
columns={ columns }
|
||||||
|
data={ this.state.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 >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
181
packages/react-bootstrap-table2-example/examples/pagination/custome-page-list-with-filter.js
vendored
Normal file
181
packages/react-bootstrap-table2-example/examples/pagination/custome-page-list-with-filter.js
vendored
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/* 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, selectFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsQualityGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsQualityGenerator(21);
|
||||||
|
|
||||||
|
const selectOptions = {
|
||||||
|
0: 'good',
|
||||||
|
1: 'Bad',
|
||||||
|
2: 'unknown'
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions[cell],
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions,
|
||||||
|
defaultValue: 0
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
import filterFactory, { textFilter, selectFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const selectOptions = {
|
||||||
|
0: 'good',
|
||||||
|
1: 'Bad',
|
||||||
|
2: 'unknown'
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions[cell],
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions,
|
||||||
|
defaultValue: 0
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
class Table extends React.Component {
|
||||||
|
state = { products }
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({ products: productsQualityGenerator(40, 7) });
|
||||||
|
}
|
||||||
|
|
||||||
|
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: this.state.products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
keyField="id"
|
||||||
|
data={ this.state.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>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class Table extends React.Component {
|
||||||
|
state = { products }
|
||||||
|
|
||||||
|
loadData = () => {
|
||||||
|
this.setState({ products: productsQualityGenerator(40, 7) });
|
||||||
|
}
|
||||||
|
|
||||||
|
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: this.state.products.length
|
||||||
|
};
|
||||||
|
const contentTable = ({ paginationProps, paginationTableProps }) => (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
|
||||||
|
<PaginationListStandalone { ...paginationProps } />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
keyField="id"
|
||||||
|
data={ this.state.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 >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
150
packages/react-bootstrap-table2-example/examples/pagination/pagination-with-dynamic-data.js
vendored
Normal file
150
packages/react-bootstrap-table2-example/examples/pagination/pagination-with-dynamic-data.js
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
|
class BookList extends React.Component {
|
||||||
|
state = {
|
||||||
|
books: [
|
||||||
|
{ id: '1', name: 'Book 1' },
|
||||||
|
{ id: '2', name: 'Book 2' },
|
||||||
|
{ id: '3', name: 'Book 3' },
|
||||||
|
{ id: '4', name: 'Book 4' },
|
||||||
|
{ id: '5', name: 'Book 5' },
|
||||||
|
{ id: '6', name: 'Book 6' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteBookWithId = () => {
|
||||||
|
const lastOneId = this.state.books.length;
|
||||||
|
const updatedBooks = this.state.books.filter(m => m.id !== lastOneId.toString());
|
||||||
|
this.setState({ books: updatedBooks });
|
||||||
|
};
|
||||||
|
|
||||||
|
addBook = () => {
|
||||||
|
const lastOneId = this.state.books.length + 1;
|
||||||
|
this.setState({ books: [...this.state.books, {
|
||||||
|
id: \`$\{lastOneId}\`, name: \`Book $\{lastOneId}\`
|
||||||
|
}] });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const options = {
|
||||||
|
// pageStartIndex: 0,
|
||||||
|
sizePerPage: 5,
|
||||||
|
hideSizePerPage: true,
|
||||||
|
hidePageListOnlyOnePage: true
|
||||||
|
};
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
Cell: row => (
|
||||||
|
<div>
|
||||||
|
<span title={ row.value }>{ row.value }</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ this.state.books }
|
||||||
|
columns={ columns }
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
/>
|
||||||
|
<button className="btn btn-default" onClick={ () => this.deleteBookWithId() }>
|
||||||
|
delete last one book
|
||||||
|
</button>
|
||||||
|
<button className="btn btn-default" onClick={ () => this.addBook() }>
|
||||||
|
Add a book to the end
|
||||||
|
</button>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class BookList extends React.Component {
|
||||||
|
state = {
|
||||||
|
books: [
|
||||||
|
{ id: '1', name: 'Book 1' },
|
||||||
|
{ id: '2', name: 'Book 2' },
|
||||||
|
{ id: '3', name: 'Book 3' },
|
||||||
|
{ id: '4', name: 'Book 4' },
|
||||||
|
{ id: '5', name: 'Book 5' },
|
||||||
|
{ id: '6', name: 'Book 6' },
|
||||||
|
{ id: '7', name: 'Book 6' },
|
||||||
|
{ id: '8', name: 'Book 6' },
|
||||||
|
{ id: '9', name: 'Book 6' },
|
||||||
|
{ id: '10', name: 'Book 6' },
|
||||||
|
{ id: '11', name: 'Book 6' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteBookWithId = () => {
|
||||||
|
const lastOneId = this.state.books.length;
|
||||||
|
const updatedBooks = this.state.books.filter(m => m.id !== lastOneId.toString());
|
||||||
|
this.setState({ books: updatedBooks });
|
||||||
|
};
|
||||||
|
|
||||||
|
addBook = () => {
|
||||||
|
const lastOneId = this.state.books.length + 1;
|
||||||
|
this.setState({ books: [...this.state.books, {
|
||||||
|
id: `${lastOneId}`, name: `Book ${lastOneId}`
|
||||||
|
}] });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const options = {
|
||||||
|
// pageStartIndex: 0,
|
||||||
|
sizePerPage: 5,
|
||||||
|
hideSizePerPage: true,
|
||||||
|
hidePageListOnlyOnePage: true
|
||||||
|
};
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
Cell: row => (
|
||||||
|
<div>
|
||||||
|
<span title={ row.value }>{ row.value }</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ this.state.books }
|
||||||
|
columns={ columns }
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
/>
|
||||||
|
<button className="btn btn-default" onClick={ () => this.deleteBookWithId() }>
|
||||||
|
delete last one book
|
||||||
|
</button>
|
||||||
|
<button className="btn btn-default" onClick={ () => this.addBook() }>
|
||||||
|
Add a book to the end
|
||||||
|
</button>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
107
packages/react-bootstrap-table2-example/examples/pagination/standalone-pagination-total.js
vendored
Normal file
107
packages/react-bootstrap-table2-example/examples/pagination/standalone-pagination-total.js
vendored
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationTotalStandalone, 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, PaginationTotalStandalone, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<PaginationTotalStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class StandalonePaginationList extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<PaginationTotalStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,6 +84,7 @@ export default class StandaloneSizePerPage extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<SizePerPageDropdownStandalone
|
<SizePerPageDropdownStandalone
|
||||||
{ ...paginationProps }
|
{ ...paginationProps }
|
||||||
|
btnContextual="btn btn-primary"
|
||||||
/>
|
/>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
|
|||||||
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.14",
|
"version": "1.0.23",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ export const withOnSale = rows => rows.map((row) => {
|
|||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
|
|
||||||
export const productsQualityGenerator = (quantity = 5) =>
|
export const productsQualityGenerator = (quantity = 5, factor = 0) =>
|
||||||
Array.from({ length: quantity }, (value, index) => ({
|
Array.from({ length: quantity }, (value, index) => ({
|
||||||
id: index,
|
id: index + factor,
|
||||||
name: `Item name ${index}`,
|
name: `Item name ${index + factor}`,
|
||||||
quality: index % 3
|
quality: index % 3
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -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()))
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import TabIndexCellTable from 'examples/basic/tabindex-column';
|
|||||||
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
|
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
|
||||||
import Bootstrap4RowSelectionTable from 'examples/bootstrap4/row-selection';
|
import Bootstrap4RowSelectionTable from 'examples/bootstrap4/row-selection';
|
||||||
import Bootstrap4PaginationTable from 'examples/bootstrap4/pagination';
|
import Bootstrap4PaginationTable from 'examples/bootstrap4/pagination';
|
||||||
|
import Bootstrap4ColumnToggleTable from 'examples/bootstrap4/column-toggle';
|
||||||
|
import ToolkitsTable from 'examples/bootstrap4/toolkits';
|
||||||
|
|
||||||
// work on columns
|
// work on columns
|
||||||
import NestedDataTable from 'examples/columns/nested-data-table';
|
import NestedDataTable from 'examples/columns/nested-data-table';
|
||||||
@@ -45,6 +47,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';
|
||||||
@@ -75,6 +89,7 @@ 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 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';
|
||||||
@@ -148,6 +163,7 @@ import ExpandHooks from 'examples/row-expand/expand-hooks';
|
|||||||
// pagination
|
// pagination
|
||||||
import PaginationTable from 'examples/pagination';
|
import PaginationTable from 'examples/pagination';
|
||||||
import PaginationHooksTable from 'examples/pagination/pagination-hooks';
|
import PaginationHooksTable from 'examples/pagination/pagination-hooks';
|
||||||
|
import PaginationWithDynamicData from 'examples/pagination/pagination-with-dynamic-data';
|
||||||
import CustomPaginationTable from 'examples/pagination/custom-pagination';
|
import CustomPaginationTable from 'examples/pagination/custom-pagination';
|
||||||
import CustomPageButtonTable from 'examples/pagination/custom-page-button';
|
import CustomPageButtonTable from 'examples/pagination/custom-page-button';
|
||||||
import CustomSizePerPageOptionTable from 'examples/pagination/custom-size-per-page-option';
|
import CustomSizePerPageOptionTable from 'examples/pagination/custom-size-per-page-option';
|
||||||
@@ -155,11 +171,15 @@ import CustomSizePerPageTable from 'examples/pagination/custom-size-per-page';
|
|||||||
import CustomPageListTable from 'examples/pagination/custom-page-list';
|
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 StandalonePaginationTotal from 'examples/pagination/standalone-pagination-total';
|
||||||
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 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';
|
||||||
@@ -172,11 +192,18 @@ import CSVFormatter from 'examples/csv/csv-column-formatter';
|
|||||||
import CustomCSVHeader from 'examples/csv/custom-csv-header';
|
import CustomCSVHeader from 'examples/csv/custom-csv-header';
|
||||||
import HideCSVColumn from 'examples/csv/hide-column';
|
import HideCSVColumn from 'examples/csv/hide-column';
|
||||||
import ExportOnlySelected from 'examples/csv/export-only-selected';
|
import ExportOnlySelected from 'examples/csv/export-only-selected';
|
||||||
|
import ExportOnlyFiltered from 'examples/csv/export-only-filtered';
|
||||||
import CSVColumnType from 'examples/csv/csv-column-type';
|
import CSVColumnType from 'examples/csv/csv-column-type';
|
||||||
import CustomCSVButton from 'examples/csv/custom-csv-button';
|
import CustomCSVButton from 'examples/csv/custom-csv-button';
|
||||||
import ExportCustomData from 'examples/csv/export-custom-data';
|
import ExportCustomData from 'examples/csv/export-custom-data';
|
||||||
import CustomCSV from 'examples/csv/custom-csv';
|
import CustomCSV from 'examples/csv/custom-csv';
|
||||||
|
|
||||||
|
// Column toggle
|
||||||
|
import BasicColumnToggle from 'examples/column-toggle';
|
||||||
|
import DefaultVisibility from 'examples/column-toggle/default-visibility';
|
||||||
|
import StylingColumnToggle from 'examples/column-toggle/styling-toggle-list';
|
||||||
|
import CustomToggleList from 'examples/column-toggle/custom-toggle-list';
|
||||||
|
|
||||||
// loading overlay
|
// loading overlay
|
||||||
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
|
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
|
||||||
import TableOverlay from 'examples/loading-overlay/table-overlay';
|
import TableOverlay from 'examples/loading-overlay/table-overlay';
|
||||||
@@ -189,6 +216,13 @@ import RemoteSearch from 'examples/remote/remote-search';
|
|||||||
import RemoteCellEdit from 'examples/remote/remote-celledit';
|
import RemoteCellEdit from 'examples/remote/remote-celledit';
|
||||||
import RemoteAll from 'examples/remote/remote-all';
|
import RemoteAll from 'examples/remote/remote-all';
|
||||||
|
|
||||||
|
// data
|
||||||
|
import LoadDataWithFilter from 'examples/data/load-data-on-the-fly-with-filter';
|
||||||
|
import LoadDataWithDefaultFilter from 'examples/data/load-data-on-the-fly-with-default-filter';
|
||||||
|
import LoadDataWithSearch from 'examples/data/load-data-on-the-fly-with-search';
|
||||||
|
import LoadDataWithDefaultSearch from 'examples/data/load-data-on-the-fly-with-default-search';
|
||||||
|
import LoadDataWithPaginationAndFilter from 'examples/data/load-data-on-the-fly-with-pagination-and-filter';
|
||||||
|
|
||||||
// css style
|
// css style
|
||||||
import 'stories/stylesheet/tomorrow.min.css';
|
import 'stories/stylesheet/tomorrow.min.css';
|
||||||
import 'stories/stylesheet/storybook.scss';
|
import 'stories/stylesheet/storybook.scss';
|
||||||
@@ -199,8 +233,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())
|
||||||
@@ -218,7 +251,9 @@ storiesOf('Bootstrap 4', module)
|
|||||||
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
|
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
|
||||||
.add('Sort table with bootstrap 4', () => <Bootstrap4DefaultSortTable />)
|
.add('Sort table with bootstrap 4', () => <Bootstrap4DefaultSortTable />)
|
||||||
.add('Row selection table with bootstrap 4', () => <Bootstrap4RowSelectionTable />)
|
.add('Row selection table with bootstrap 4', () => <Bootstrap4RowSelectionTable />)
|
||||||
.add('Pagination table with bootstrap 4', () => <Bootstrap4PaginationTable />);
|
.add('Pagination table with bootstrap 4', () => <Bootstrap4PaginationTable />)
|
||||||
|
.add('Column Toggle with bootstrap 4', () => <Bootstrap4ColumnToggleTable />)
|
||||||
|
.add('toolkits Table bootstrap 4', () => <ToolkitsTable />);
|
||||||
|
|
||||||
storiesOf('Work on Columns', module)
|
storiesOf('Work on Columns', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
@@ -277,7 +312,8 @@ storiesOf('Column Filter', module)
|
|||||||
.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('Filter Hooks', () => <FilterHooks />)
|
||||||
|
.add('Implement custom filter logic', () => <CustomFilterLogic />);
|
||||||
|
|
||||||
storiesOf('Work on Rows', module)
|
storiesOf('Work on Rows', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
@@ -286,6 +322,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 />)
|
||||||
@@ -357,6 +406,7 @@ storiesOf('Pagination', module)
|
|||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Basic Pagination Table', () => <PaginationTable />)
|
.add('Basic Pagination Table', () => <PaginationTable />)
|
||||||
.add('Pagination Hooks', () => <PaginationHooksTable />)
|
.add('Pagination Hooks', () => <PaginationHooksTable />)
|
||||||
|
.add('Pagination with Dynamic Data', () => <PaginationWithDynamicData />)
|
||||||
.add('Custom Pagination', () => <CustomPaginationTable />)
|
.add('Custom Pagination', () => <CustomPaginationTable />)
|
||||||
.add('Custom Page Button', () => <CustomPageButtonTable />)
|
.add('Custom Page Button', () => <CustomPageButtonTable />)
|
||||||
.add('Custom Page List', () => <CustomPageListTable />)
|
.add('Custom Page List', () => <CustomPageListTable />)
|
||||||
@@ -364,18 +414,29 @@ 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('Standalone Pagination Total', () => <StandalonePaginationTotal />)
|
||||||
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />)
|
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />)
|
||||||
.add('Remote Fully Custom Pagination', () => <RemoteStandalonePaginationTable />);
|
.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 />)
|
||||||
.add('Search Fromatted Value', () => <SearchFormattedData />)
|
.add('Search Fromatted Value', () => <SearchFormattedData />)
|
||||||
.add('Custom Search Value', () => <CustomSearchValue />);
|
.add('Custom Search Value', () => <CustomSearchValue />);
|
||||||
|
|
||||||
|
storiesOf('Column Toggle', module)
|
||||||
|
.addDecorator(bootstrapStyle())
|
||||||
|
.add('Basic Column Toggle', () => <BasicColumnToggle />)
|
||||||
|
.add('Default Visibility', () => <DefaultVisibility />)
|
||||||
|
.add('Styling Column Toggle', () => <StylingColumnToggle />)
|
||||||
|
.add('Custom Column Toggle', () => <CustomToggleList />);
|
||||||
|
|
||||||
storiesOf('Export CSV', module)
|
storiesOf('Export CSV', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Basic Export CSV', () => <ExportCSV />)
|
.add('Basic Export CSV', () => <ExportCSV />)
|
||||||
@@ -383,6 +444,7 @@ storiesOf('Export CSV', module)
|
|||||||
.add('Custom CSV Header', () => <CustomCSVHeader />)
|
.add('Custom CSV Header', () => <CustomCSVHeader />)
|
||||||
.add('Hide CSV Column', () => <HideCSVColumn />)
|
.add('Hide CSV Column', () => <HideCSVColumn />)
|
||||||
.add('Only Export Selected Rows', () => <ExportOnlySelected />)
|
.add('Only Export Selected Rows', () => <ExportOnlySelected />)
|
||||||
|
.add('Only Export Filtered/Searched Rows', () => <ExportOnlyFiltered />)
|
||||||
.add('CSV Column Type', () => <CSVColumnType />)
|
.add('CSV Column Type', () => <CSVColumnType />)
|
||||||
.add('Custom CSV Button', () => <CustomCSVButton />)
|
.add('Custom CSV Button', () => <CustomCSVButton />)
|
||||||
.add('Export Custom Data', () => <ExportCustomData />)
|
.add('Export Custom Data', () => <ExportCustomData />)
|
||||||
@@ -401,3 +463,11 @@ storiesOf('Remote', module)
|
|||||||
.add('Remote Search', () => <RemoteSearch />)
|
.add('Remote Search', () => <RemoteSearch />)
|
||||||
.add('Remote Cell Editing', () => <RemoteCellEdit />)
|
.add('Remote Cell Editing', () => <RemoteCellEdit />)
|
||||||
.add('Remote All', () => <RemoteAll />);
|
.add('Remote All', () => <RemoteAll />);
|
||||||
|
|
||||||
|
storiesOf('Data', module)
|
||||||
|
.addDecorator(bootstrapStyle())
|
||||||
|
.add('Load data with Filter', () => <LoadDataWithFilter />)
|
||||||
|
.add('Load data with Default Filter', () => <LoadDataWithDefaultFilter />)
|
||||||
|
.add('Load data with Search', () => <LoadDataWithSearch />)
|
||||||
|
.add('Load data with Default Search', () => <LoadDataWithDefaultSearch />)
|
||||||
|
.add('Load data with Filter and Pagination', () => <LoadDataWithPaginationAndFilter />);
|
||||||
|
|||||||
@@ -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.1",
|
"version": "1.1.8",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const legalComparators = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
function dateParser(d) {
|
function dateParser(d) {
|
||||||
return `${d.getFullYear()}-${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + d.getDate()).slice(-2)}`;
|
return `${d.getUTCFullYear()}-${('0' + (d.getUTCMonth() + 1)).slice(-2)}-${('0' + d.getUTCDate()).slice(-2)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DateFilter extends Component {
|
class DateFilter extends Component {
|
||||||
@@ -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,14 +17,18 @@ 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) {
|
||||||
super(props);
|
super(props);
|
||||||
this.currFilters = {};
|
this.currFilters = {};
|
||||||
this.onFilter = this.onFilter.bind(this);
|
this.onFilter = this.onFilter.bind(this);
|
||||||
|
this.doFilter = this.doFilter.bind(this);
|
||||||
this.onExternalFilter = this.onExternalFilter.bind(this);
|
this.onExternalFilter = this.onExternalFilter.bind(this);
|
||||||
|
this.data = props.data;
|
||||||
|
this.isEmitDataChange = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -33,6 +37,15 @@ export default (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
// let nextData = nextProps.data;
|
||||||
|
if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.data)) {
|
||||||
|
this.doFilter(nextProps, undefined, this.isEmitDataChange);
|
||||||
|
} else {
|
||||||
|
this.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,11 +77,11 @@ export default (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let result;
|
||||||
if (filter.props.onFilter) {
|
if (filter.props.onFilter) {
|
||||||
filter.props.onFilter(filterVal);
|
result = filter.props.onFilter(filterVal);
|
||||||
}
|
}
|
||||||
|
this.doFilter(this.props, result);
|
||||||
this.forceUpdate();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,14 +91,29 @@ export default (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
getFiltered() {
|
||||||
let { data } = this.props;
|
return this.data;
|
||||||
if (!isRemoteFiltering()) {
|
}
|
||||||
data = filters(data, this.props.columns, _)(this.currFilters);
|
|
||||||
|
doFilter(props, customResult, ignoreEmitDataChange = false) {
|
||||||
|
let result = customResult;
|
||||||
|
|
||||||
|
const { dataChangeListener, data, columns } = props;
|
||||||
|
result = result || filters(data, columns, _)(this.currFilters);
|
||||||
|
this.data = result;
|
||||||
|
if (dataChangeListener && !ignoreEmitDataChange) {
|
||||||
|
this.isEmitDataChange = true;
|
||||||
|
dataChangeListener.emit('filterChanged', result.length);
|
||||||
|
} else {
|
||||||
|
this.isEmitDataChange = false;
|
||||||
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<FilterContext.Provider value={ {
|
<FilterContext.Provider value={ {
|
||||||
data,
|
data: this.data,
|
||||||
onFilter: this.onFilter,
|
onFilter: this.onFilter,
|
||||||
onExternalFilter: this.onExternalFilter
|
onExternalFilter: this.onExternalFilter
|
||||||
} }
|
} }
|
||||||
|
|||||||
@@ -98,9 +98,9 @@ export const filterByDate = _ => (
|
|||||||
customFilterValue
|
customFilterValue
|
||||||
) => {
|
) => {
|
||||||
if (!date || !comparator) return data;
|
if (!date || !comparator) return data;
|
||||||
const filterDate = date.getDate();
|
const filterDate = date.getUTCDate();
|
||||||
const filterMonth = date.getMonth();
|
const filterMonth = date.getUTCMonth();
|
||||||
const filterYear = date.getFullYear();
|
const filterYear = date.getUTCFullYear();
|
||||||
|
|
||||||
return data.filter((row) => {
|
return data.filter((row) => {
|
||||||
let valid = true;
|
let valid = true;
|
||||||
@@ -114,9 +114,9 @@ export const filterByDate = _ => (
|
|||||||
cell = new Date(cell);
|
cell = new Date(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetDate = cell.getDate();
|
const targetDate = cell.getUTCDate();
|
||||||
const targetMonth = cell.getMonth();
|
const targetMonth = cell.getUTCMonth();
|
||||||
const targetYear = cell.getFullYear();
|
const targetYear = cell.getUTCFullYear();
|
||||||
|
|
||||||
|
|
||||||
switch (comparator) {
|
switch (comparator) {
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ describe('FilterContext', () => {
|
|||||||
|
|
||||||
function shallowContext(
|
function shallowContext(
|
||||||
enableRemote = false,
|
enableRemote = false,
|
||||||
tableColumns = columns
|
tableColumns = columns,
|
||||||
|
dataChangeListener,
|
||||||
) {
|
) {
|
||||||
mockBase.mockReset();
|
mockBase.mockReset();
|
||||||
handleFilterChange.mockReset();
|
handleFilterChange.mockReset();
|
||||||
@@ -59,6 +60,7 @@ describe('FilterContext', () => {
|
|||||||
<FilterContext.Provider
|
<FilterContext.Provider
|
||||||
columns={ tableColumns }
|
columns={ tableColumns }
|
||||||
data={ data }
|
data={ data }
|
||||||
|
dataChangeListener={ dataChangeListener }
|
||||||
>
|
>
|
||||||
<FilterContext.Consumer>
|
<FilterContext.Consumer>
|
||||||
{
|
{
|
||||||
@@ -252,6 +254,58 @@ describe('FilterContext', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 data correctly', () => {
|
||||||
|
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
|
||||||
|
expect(instance.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());
|
||||||
|
|||||||
@@ -69,23 +69,23 @@ Sometime, you may feel above props is not satisfied with your requirement, don't
|
|||||||
* [sizePerPageOptionRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationsizeperpageoptionrenderer-function)
|
* [sizePerPageOptionRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationsizeperpageoptionrenderer-function)
|
||||||
* [paginationTotalRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationpaginationtotalrenderer-function)
|
* [paginationTotalRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationpaginationtotalrenderer-function)
|
||||||
|
|
||||||
### Professional
|
### Fully Customization
|
||||||
|
|
||||||
If you want to customize the pagination component completely, you may get interesting on following solution:
|
If you want to customize the pagination component completely, you may get interesting on following solutions:
|
||||||
|
|
||||||
* Standalone
|
* Standalone
|
||||||
* Non-standalone
|
* Non-standalone
|
||||||
|
|
||||||
`react-bootstrap-table2-paginator` have a `PaginationProvider` which is a react context and you will be easier to customize the pagination components under the scope of `PaginationProvider`. Let's introduce it step by step:
|
`react-bootstrap-table2-paginator` have a `PaginationProvider` which is a react context and that will be easier to customize the pagination components under the scope of `PaginationProvider`. Let's introduce it step by step:
|
||||||
|
|
||||||
#### Import PaginationProvider
|
#### 1. Import PaginationProvider
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import paginationFactory, { PaginationProvider } from 'react-bootstrap-table2-paginator';
|
import paginationFactory, { PaginationProvider } from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Declare custom and totalSize in pagination option:
|
#### 2. Declare custom and totalSize in pagination option:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const paginationOption = {
|
const paginationOption = {
|
||||||
@@ -94,7 +94,7 @@ const paginationOption = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Render PaginationProvider
|
#### 3. Render PaginationProvider
|
||||||
|
|
||||||
```js
|
```js
|
||||||
<PaginationProvider
|
<PaginationProvider
|
||||||
@@ -139,18 +139,24 @@ So far, your customization pagination is supposed to look like it:
|
|||||||
</PaginationProvider>
|
</PaginationProvider>
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, you have to choose, your built-in standalne components or you customize all of them by yourself:
|
Now, you have to choose which solution you like: standalone or non-standalone ?
|
||||||
|
|
||||||
#### Use Standalone Component
|
#### 4.1 Use Standalone Component
|
||||||
`react-bootstrap-table2-paginator` provider two standalone components:
|
`react-bootstrap-table2-paginator` provider three standalone components:
|
||||||
|
|
||||||
* Size Per Page Dropdwn Standalone
|
* Size Per Page Dropdwn Standalone
|
||||||
* Pagination List Standalone
|
* Pagination List Standalone
|
||||||
|
* Pagination Total Standalone
|
||||||
|
|
||||||
When render each standalone, you just need to pass the `paginationProps` props to standalone component:
|
When render each standalone, you just need to pass the `paginationProps` props to standalone component:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import paginationFactory, { PaginationProvider, PaginationListStandalone, SizePerPageDropdownStandalone } from 'react-bootstrap-table2-paginator';
|
import paginationFactory, {
|
||||||
|
PaginationProvider,
|
||||||
|
PaginationListStandalone,
|
||||||
|
SizePerPageDropdownStandalone,
|
||||||
|
PaginationTotalStandalone
|
||||||
|
} from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
<PaginationProvider
|
<PaginationProvider
|
||||||
pagination={ paginationFactory(options) }
|
pagination={ paginationFactory(options) }
|
||||||
@@ -164,6 +170,9 @@ import paginationFactory, { PaginationProvider, PaginationListStandalone, SizePe
|
|||||||
<SizePerPageDropdownStandalone
|
<SizePerPageDropdownStandalone
|
||||||
{ ...paginationProps }
|
{ ...paginationProps }
|
||||||
/>
|
/>
|
||||||
|
<PaginationTotalStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ products }
|
data={ products }
|
||||||
@@ -181,7 +190,20 @@ import paginationFactory, { PaginationProvider, PaginationListStandalone, SizePe
|
|||||||
|
|
||||||
That's it!! The benifit for using standalone is you can much easier to render the standalone component in any posistion. In the future, we will implement more featue like applying `style`, `className` etc on standalone components.
|
That's it!! The benifit for using standalone is you can much easier to render the standalone component in any posistion. In the future, we will implement more featue like applying `style`, `className` etc on standalone components.
|
||||||
|
|
||||||
#### Customization Everything
|
##### Customizable props for `PaginationListStandalone`
|
||||||
|
* N/A
|
||||||
|
|
||||||
|
##### Customizable props for `SizePerPageDropdownStandalone`
|
||||||
|
* `open`: `true` to make dropdown show.
|
||||||
|
* `hidden`: `true` to hide the size per page dropdown.
|
||||||
|
* `btnContextual`: Set the button contextual
|
||||||
|
* `variation`: Variation for dropdown, available value is `dropdown` and `dropup`.
|
||||||
|
* `className`: Custom the class on size per page dropdown
|
||||||
|
|
||||||
|
##### Customizable props for `SizePerPageDropdownStandalone`
|
||||||
|
* N/A
|
||||||
|
|
||||||
|
#### 4.2 Customization Everything
|
||||||
|
|
||||||
If you choose to custom the pagination component by yourself, the `paginationProps` will be important for you. Becasue you have to know for example how to change page or what's the current page etc. Hence, following is all the props in `paginationProps` object:
|
If you choose to custom the pagination component by yourself, the `paginationProps` will be important for you. Becasue you have to know for example how to change page or what's the current page etc. Hence, following is all the props in `paginationProps` object:
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import createBaseContext from './src/state-context';
|
|||||||
import createDataContext from './src/data-context';
|
import createDataContext from './src/data-context';
|
||||||
import PaginationListStandalone from './src/pagination-list-standalone';
|
import PaginationListStandalone from './src/pagination-list-standalone';
|
||||||
import SizePerPageDropdownStandalone from './src/size-per-page-dropdown-standalone';
|
import SizePerPageDropdownStandalone from './src/size-per-page-dropdown-standalone';
|
||||||
|
import PaginationTotalStandalone from './src/pagination-total-standalone';
|
||||||
|
|
||||||
export default (options = {}) => ({
|
export default (options = {}) => ({
|
||||||
createContext: createDataContext,
|
createContext: createDataContext,
|
||||||
@@ -23,4 +24,4 @@ CustomizableProvider.propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const PaginationProvider = CustomizableProvider;
|
export const PaginationProvider = CustomizableProvider;
|
||||||
export { PaginationListStandalone, SizePerPageDropdownStandalone };
|
export { PaginationListStandalone, SizePerPageDropdownStandalone, PaginationTotalStandalone };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-paginator",
|
"name": "react-bootstrap-table2-paginator",
|
||||||
"version": "2.0.1",
|
"version": "2.0.5",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -32,7 +32,12 @@ class PaginationDataProvider extends Provider {
|
|||||||
// user should align the page when the page is not fit to the data size when remote enable
|
// user should align the page when the page is not fit to the data size when remote enable
|
||||||
if (!this.isRemotePagination() && !custom) {
|
if (!this.isRemotePagination() && !custom) {
|
||||||
const newPage = alignPage(
|
const newPage = alignPage(
|
||||||
nextProps.data.length, this.currPage, currSizePerPage, pageStartIndex);
|
nextProps.data.length,
|
||||||
|
this.props.data.length,
|
||||||
|
this.currPage,
|
||||||
|
currSizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
);
|
||||||
|
|
||||||
if (this.currPage !== newPage) {
|
if (this.currPage !== newPage) {
|
||||||
if (onPageChange) {
|
if (onPageChange) {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default ExtendBase =>
|
|||||||
alwaysShowAllBtns
|
alwaysShowAllBtns
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let pages;
|
let pages = [];
|
||||||
let endPage = totalPages;
|
let endPage = totalPages;
|
||||||
if (endPage <= 0) return [];
|
if (endPage <= 0) return [];
|
||||||
|
|
||||||
@@ -68,24 +68,42 @@ export default ExtendBase =>
|
|||||||
startPage = endPage - paginationSize + 1;
|
startPage = endPage - paginationSize + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startPage !== pageStartIndex && totalPages > paginationSize && withFirstAndLast) {
|
if (alwaysShowAllBtns) {
|
||||||
|
if (withFirstAndLast) {
|
||||||
|
pages = [firstPageText, prePageText];
|
||||||
|
} else {
|
||||||
|
pages = [prePageText];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startPage !== pageStartIndex &&
|
||||||
|
totalPages > paginationSize &&
|
||||||
|
withFirstAndLast &&
|
||||||
|
pages.length === 0
|
||||||
|
) {
|
||||||
pages = [firstPageText, prePageText];
|
pages = [firstPageText, prePageText];
|
||||||
} else if (totalPages > 1 || alwaysShowAllBtns) {
|
} else if (totalPages > 1 && pages.length === 0) {
|
||||||
pages = [prePageText];
|
pages = [prePageText];
|
||||||
} else {
|
|
||||||
pages = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = startPage; i <= endPage; i += 1) {
|
for (let i = startPage; i <= endPage; i += 1) {
|
||||||
if (i >= pageStartIndex) pages.push(i);
|
if (i >= pageStartIndex) pages.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endPage <= lastPage && pages.length > 1) {
|
if (alwaysShowAllBtns || (endPage <= lastPage && pages.length > 1)) {
|
||||||
pages.push(nextPageText);
|
pages.push(nextPageText);
|
||||||
}
|
}
|
||||||
if (endPage !== lastPage && withFirstAndLast) {
|
if ((endPage !== lastPage && withFirstAndLast) || (withFirstAndLast && alwaysShowAllBtns)) {
|
||||||
pages.push(lastPageText);
|
pages.push(lastPageText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if ((endPage <= lastPage && pages.length > 1) || alwaysShowAllBtns) {
|
||||||
|
// pages.push(nextPageText);
|
||||||
|
// }
|
||||||
|
// if (endPage !== lastPage && withFirstAndLast) {
|
||||||
|
// pages.push(lastPageText);
|
||||||
|
// }
|
||||||
|
|
||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import Const from './const';
|
||||||
|
|
||||||
const getNormalizedPage = (
|
const getNormalizedPage = (
|
||||||
page,
|
page,
|
||||||
pageStartIndex
|
pageStartIndex
|
||||||
@@ -19,12 +21,20 @@ const startIndex = (
|
|||||||
|
|
||||||
export const alignPage = (
|
export const alignPage = (
|
||||||
dataSize,
|
dataSize,
|
||||||
|
prevDataSize,
|
||||||
page,
|
page,
|
||||||
sizePerPage,
|
sizePerPage,
|
||||||
pageStartIndex
|
pageStartIndex
|
||||||
) => {
|
) => {
|
||||||
if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) {
|
if (prevDataSize < dataSize) return page;
|
||||||
return pageStartIndex;
|
if (page < pageStartIndex) return pageStartIndex;
|
||||||
|
if (dataSize <= 0) return pageStartIndex;
|
||||||
|
if ((page >= (Math.floor(dataSize / sizePerPage) + pageStartIndex)) && pageStartIndex === 1) {
|
||||||
|
return Math.ceil(dataSize / sizePerPage);
|
||||||
|
}
|
||||||
|
if (page >= Math.floor(dataSize / sizePerPage) && pageStartIndex === 0) {
|
||||||
|
const newPage = Math.ceil(dataSize / sizePerPage);
|
||||||
|
return newPage - Math.abs((Const.PAGE_START_INDEX - pageStartIndex));
|
||||||
}
|
}
|
||||||
return page;
|
return page;
|
||||||
};
|
};
|
||||||
|
|||||||
24
packages/react-bootstrap-table2-paginator/src/pagination-total-adapter.js
vendored
Normal file
24
packages/react-bootstrap-table2-paginator/src/pagination-total-adapter.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import pageResolver from './page-resolver';
|
||||||
|
import PaginationTotal from './pagination-total';
|
||||||
|
|
||||||
|
const paginationTotalAdapter = WrappedComponent =>
|
||||||
|
class PaginationTotalAdapter extends pageResolver(Component) {
|
||||||
|
render() {
|
||||||
|
const [from, to] = this.calculateFromTo();
|
||||||
|
return (
|
||||||
|
<WrappedComponent
|
||||||
|
from={ from }
|
||||||
|
to={ to }
|
||||||
|
dataSize={ this.props.dataSize }
|
||||||
|
paginationTotalRenderer={ this.props.paginationTotalRenderer }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const PaginationTotalWithAdapter = paginationTotalAdapter(PaginationTotal);
|
||||||
|
export default paginationTotalAdapter;
|
||||||
11
packages/react-bootstrap-table2-paginator/src/pagination-total-standalone.js
vendored
Normal file
11
packages/react-bootstrap-table2-paginator/src/pagination-total-standalone.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PaginationTotal from './pagination-total';
|
||||||
|
import standaloneAdapter from './standalone-adapter';
|
||||||
|
import paginationTotalAdapter from './pagination-total-adapter';
|
||||||
|
|
||||||
|
const PaginationTotalStandalone = props => (
|
||||||
|
<PaginationTotal { ...props } />
|
||||||
|
);
|
||||||
|
|
||||||
|
export default
|
||||||
|
standaloneAdapter(paginationTotalAdapter(PaginationTotalStandalone));
|
||||||
@@ -1,16 +1,26 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const PaginationTotal = props => (
|
const PaginationTotal = (props) => {
|
||||||
<span className="react-bootstrap-table-pagination-total">
|
if (props.paginationTotalRenderer) {
|
||||||
Showing rows { props.from } to { props.to } of { props.dataSize }
|
return props.paginationTotalRenderer(props.from, props.to, props.dataSize);
|
||||||
</span>
|
}
|
||||||
);
|
return (
|
||||||
|
<span className="react-bootstrap-table-pagination-total">
|
||||||
|
Showing rows { props.from } to { props.to } of { props.dataSize }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
PaginationTotal.propTypes = {
|
PaginationTotal.propTypes = {
|
||||||
from: PropTypes.number.isRequired,
|
from: PropTypes.number.isRequired,
|
||||||
to: PropTypes.number.isRequired,
|
to: PropTypes.number.isRequired,
|
||||||
dataSize: PropTypes.number.isRequired
|
dataSize: PropTypes.number.isRequired,
|
||||||
|
paginationTotalRenderer: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
PaginationTotal.defaultProps = {
|
||||||
|
paginationTotalRenderer: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PaginationTotal;
|
export default PaginationTotal;
|
||||||
|
|||||||
@@ -5,30 +5,16 @@ import React, { Component } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import pageResolver from './page-resolver';
|
import pageResolver from './page-resolver';
|
||||||
import paginationHandler from './pagination-handler';
|
import paginationHandler from './pagination-handler';
|
||||||
import { SizePerPageDropdownAdapter } from './size-per-page-dropdown-adapter';
|
import { SizePerPageDropdownWithAdapter } from './size-per-page-dropdown-adapter';
|
||||||
import { PaginationListWithAdapter } from './pagination-list-adapter';
|
import { PaginationListWithAdapter } from './pagination-list-adapter';
|
||||||
import PaginationTotal from './pagination-total';
|
import { PaginationTotalWithAdapter } from './pagination-total-adapter';
|
||||||
import Const from './const';
|
import Const from './const';
|
||||||
|
|
||||||
class Pagination extends pageResolver(Component) {
|
class Pagination extends pageResolver(Component) {
|
||||||
defaultTotal = (from, to, size) => (
|
|
||||||
<PaginationTotal
|
|
||||||
from={ from }
|
|
||||||
to={ to }
|
|
||||||
dataSize={ size }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
setTotal = (from, to, size, total) => {
|
|
||||||
if (total && (typeof total === 'function')) {
|
|
||||||
return total(from, to, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.defaultTotal(from, to, size);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
currPage,
|
||||||
|
pageStartIndex,
|
||||||
showTotal,
|
showTotal,
|
||||||
dataSize,
|
dataSize,
|
||||||
pageListRenderer,
|
pageListRenderer,
|
||||||
@@ -48,7 +34,6 @@ class Pagination extends pageResolver(Component) {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const pages = this.calculatePageStatus(this.calculatePages(totalPages, lastPage), lastPage);
|
const pages = this.calculatePageStatus(this.calculatePages(totalPages, lastPage), lastPage);
|
||||||
const [from, to] = this.calculateFromTo();
|
|
||||||
const pageListClass = cs(
|
const pageListClass = cs(
|
||||||
'react-bootstrap-table-pagination-list',
|
'react-bootstrap-table-pagination-list',
|
||||||
'col-md-6 col-xs-6 col-sm-6 col-lg-6', {
|
'col-md-6 col-xs-6 col-sm-6 col-lg-6', {
|
||||||
@@ -57,7 +42,7 @@ class Pagination extends pageResolver(Component) {
|
|||||||
return (
|
return (
|
||||||
<div className="row react-bootstrap-table-pagination">
|
<div className="row react-bootstrap-table-pagination">
|
||||||
<div className="col-md-6 col-xs-6 col-sm-6 col-lg-6">
|
<div className="col-md-6 col-xs-6 col-sm-6 col-lg-6">
|
||||||
<SizePerPageDropdownAdapter
|
<SizePerPageDropdownWithAdapter
|
||||||
sizePerPageList={ sizePerPageList }
|
sizePerPageList={ sizePerPageList }
|
||||||
currSizePerPage={ currSizePerPage }
|
currSizePerPage={ currSizePerPage }
|
||||||
hideSizePerPage={ hideSizePerPage }
|
hideSizePerPage={ hideSizePerPage }
|
||||||
@@ -67,12 +52,13 @@ class Pagination extends pageResolver(Component) {
|
|||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
showTotal ?
|
showTotal ?
|
||||||
this.setTotal(
|
<PaginationTotalWithAdapter
|
||||||
from,
|
currPage={ currPage }
|
||||||
to,
|
currSizePerPage={ currSizePerPage }
|
||||||
dataSize,
|
pageStartIndex={ pageStartIndex }
|
||||||
paginationTotalRenderer
|
dataSize={ dataSize }
|
||||||
) : null
|
paginationTotalRenderer={ paginationTotalRenderer }
|
||||||
|
/> : null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
@@ -83,6 +69,9 @@ class Pagination extends pageResolver(Component) {
|
|||||||
<div className={ pageListClass }>
|
<div className={ pageListClass }>
|
||||||
<PaginationListWithAdapter
|
<PaginationListWithAdapter
|
||||||
{ ...rest }
|
{ ...rest }
|
||||||
|
currPage={ currPage }
|
||||||
|
currSizePerPage={ currSizePerPage }
|
||||||
|
pageStartIndex={ pageStartIndex }
|
||||||
lastPage={ lastPage }
|
lastPage={ lastPage }
|
||||||
totalPages={ totalPages }
|
totalPages={ totalPages }
|
||||||
pageButtonRenderer={ pageButtonRenderer }
|
pageButtonRenderer={ pageButtonRenderer }
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ const sizePerPageDropdownAdapter = WrappedComponent =>
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<WrappedComponent
|
<WrappedComponent
|
||||||
|
{ ...this.props }
|
||||||
currSizePerPage={ `${currSizePerPage}` }
|
currSizePerPage={ `${currSizePerPage}` }
|
||||||
options={ this.calculateSizePerPageStatus() }
|
options={ this.calculateSizePerPageStatus() }
|
||||||
optionRenderer={ sizePerPageOptionRenderer }
|
optionRenderer={ sizePerPageOptionRenderer }
|
||||||
@@ -63,5 +64,5 @@ const sizePerPageDropdownAdapter = WrappedComponent =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const SizePerPageDropdownAdapter = sizePerPageDropdownAdapter(SizePerPageDropDown);
|
export const SizePerPageDropdownWithAdapter = sizePerPageDropdownAdapter(SizePerPageDropDown);
|
||||||
export default sizePerPageDropdownAdapter;
|
export default sizePerPageDropdownAdapter;
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -44,14 +50,21 @@ class StateProvider extends React.Component {
|
|||||||
|
|
||||||
// user should align the page when the page is not fit to the data size when remote enable
|
// user should align the page when the page is not fit to the data size when remote enable
|
||||||
if (this.isRemotePagination() || custom) {
|
if (this.isRemotePagination() || custom) {
|
||||||
this.currPage = nextProps.pagination.options.page;
|
if (typeof nextProps.pagination.options.page !== 'undefined') {
|
||||||
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
this.currPage = nextProps.pagination.options.page;
|
||||||
|
}
|
||||||
|
if (typeof nextProps.pagination.options.sizePerPage !== 'undefined') {
|
||||||
|
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||||
|
}
|
||||||
|
if (typeof nextProps.pagination.options.totalSize !== 'undefined') {
|
||||||
|
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 +85,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 +119,21 @@ 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.currPage = alignPage(
|
||||||
|
newDataSize,
|
||||||
|
this.dataSize,
|
||||||
|
this.currPage,
|
||||||
|
this.currSizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
);
|
||||||
|
this.dataSize = newDataSize;
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
handleChangePage(currPage) {
|
handleChangePage(currPage) {
|
||||||
const { currSizePerPage } = this;
|
const { currSizePerPage } = this;
|
||||||
const { pagination: { options } } = this.props;
|
const { pagination: { options } } = this.props;
|
||||||
@@ -153,7 +181,8 @@ class StateProvider extends React.Component {
|
|||||||
paginationProps,
|
paginationProps,
|
||||||
paginationTableProps: {
|
paginationTableProps: {
|
||||||
pagination,
|
pagination,
|
||||||
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter
|
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter,
|
||||||
|
dataChangeListener: this.dataChangeListener
|
||||||
}
|
}
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -43,18 +43,132 @@ describe('Page Functions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('alignPage', () => {
|
describe('alignPage', () => {
|
||||||
const pageStartIndex = 1;
|
let newDataSize;
|
||||||
const sizePerPage = 10;
|
let prevDataSize;
|
||||||
const page = 3;
|
let currPage;
|
||||||
describe('if the page does not fit the pages which calculated from the length of data', () => {
|
let pageStartIndex;
|
||||||
it('should return pageStartIndex argument', () => {
|
let sizePerPage;
|
||||||
expect(alignPage(15, page, sizePerPage, pageStartIndex)).toEqual(pageStartIndex);
|
|
||||||
|
describe('if prevDataSize < newDataSize', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
newDataSize = 10;
|
||||||
|
prevDataSize = 6;
|
||||||
|
currPage = 2;
|
||||||
|
pageStartIndex = 1;
|
||||||
|
sizePerPage = 5;
|
||||||
|
});
|
||||||
|
it('should return same page', () => {
|
||||||
|
expect(alignPage(
|
||||||
|
newDataSize,
|
||||||
|
prevDataSize,
|
||||||
|
currPage,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
)).toEqual(currPage);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if the length of store.data is large than the end page index', () => {
|
describe('if currPage < newDataSize', () => {
|
||||||
it('should return current page', () => {
|
beforeEach(() => {
|
||||||
expect(alignPage(30, page, sizePerPage, pageStartIndex)).toEqual(page);
|
newDataSize = 10;
|
||||||
|
prevDataSize = 12;
|
||||||
|
currPage = 0;
|
||||||
|
pageStartIndex = 1;
|
||||||
|
sizePerPage = 5;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct page', () => {
|
||||||
|
expect(alignPage(
|
||||||
|
newDataSize,
|
||||||
|
prevDataSize,
|
||||||
|
currPage,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
)).toEqual(pageStartIndex);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if partStartIndex is default 1', () => {
|
||||||
|
describe('and currPage is bigger than newest last page', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
newDataSize = 9;
|
||||||
|
prevDataSize = 12;
|
||||||
|
currPage = 3;
|
||||||
|
pageStartIndex = 1;
|
||||||
|
sizePerPage = 5;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct page', () => {
|
||||||
|
expect(alignPage(
|
||||||
|
newDataSize,
|
||||||
|
prevDataSize,
|
||||||
|
currPage,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
)).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and currPage is short than newest last page', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
newDataSize = 11;
|
||||||
|
prevDataSize = 12;
|
||||||
|
currPage = 3;
|
||||||
|
pageStartIndex = 1;
|
||||||
|
sizePerPage = 5;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct page', () => {
|
||||||
|
expect(alignPage(
|
||||||
|
newDataSize,
|
||||||
|
prevDataSize,
|
||||||
|
currPage,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
)).toEqual(currPage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if partStartIndex is default 0', () => {
|
||||||
|
describe('and currPage is bigger than newest last page', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
newDataSize = 8;
|
||||||
|
prevDataSize = 11;
|
||||||
|
currPage = 2;
|
||||||
|
pageStartIndex = 0;
|
||||||
|
sizePerPage = 5;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct page', () => {
|
||||||
|
expect(alignPage(
|
||||||
|
newDataSize,
|
||||||
|
prevDataSize,
|
||||||
|
currPage,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
)).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and currPage is short than newest last page', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
newDataSize = 11;
|
||||||
|
prevDataSize = 12;
|
||||||
|
currPage = 2;
|
||||||
|
pageStartIndex = 0;
|
||||||
|
sizePerPage = 5;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct page', () => {
|
||||||
|
expect(alignPage(
|
||||||
|
newDataSize,
|
||||||
|
prevDataSize,
|
||||||
|
currPage,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
)).toEqual(currPage);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import paginationTotalAdapter from '../src/pagination-total-adapter';
|
||||||
|
|
||||||
|
|
||||||
|
const MockComponent = () => null;
|
||||||
|
|
||||||
|
const PaginationTotalAdapter = paginationTotalAdapter(MockComponent);
|
||||||
|
|
||||||
|
describe('paginationTotalAdapter', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
dataSize: 20,
|
||||||
|
currPage: 1,
|
||||||
|
currSizePerPage: 10,
|
||||||
|
paginationTotalRenderer: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('render', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<PaginationTotalAdapter { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const mockComponent = wrapper.find(MockComponent);
|
||||||
|
expect(mockComponent).toHaveLength(1);
|
||||||
|
expect(mockComponent.props().from).toBeDefined();
|
||||||
|
expect(mockComponent.props().to).toBeDefined();
|
||||||
|
expect(mockComponent.props().dataSize).toEqual(props.dataSize);
|
||||||
|
expect(mockComponent.props().paginationTotalRenderer).toEqual(props.paginationTotalRenderer);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow, render } from 'enzyme';
|
||||||
|
|
||||||
import SizePerPageDropDown from '../src/size-per-page-dropdown';
|
import SizePerPageDropDown from '../src/size-per-page-dropdown';
|
||||||
import PaginationList from '../src/pagination-list';
|
import PaginationList from '../src/pagination-list';
|
||||||
import Pagination from '../src/pagination';
|
import Pagination from '../src/pagination';
|
||||||
import PaginationTotal from '../src/pagination-total';
|
|
||||||
|
|
||||||
describe('Pagination', () => {
|
describe('Pagination', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
@@ -107,28 +106,24 @@ describe('Pagination', () => {
|
|||||||
describe('when props.showTotal is true', () => {
|
describe('when props.showTotal is true', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const props = createMockProps({ showTotal: true });
|
const props = createMockProps({ showTotal: true });
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
wrapper = render(<Pagination { ...props } />);
|
||||||
wrapper.render();
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render PaginationTotal correctly', () => {
|
it('should render PaginationTotal correctly', () => {
|
||||||
expect(wrapper.dive().find(PaginationTotal)).toHaveLength(1);
|
expect(wrapper.find('.react-bootstrap-table-pagination-total')).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if props.paginationTotalRenderer is defined', () => {
|
describe('if props.paginationTotalRenderer is defined', () => {
|
||||||
let paginationTotalRenderer;
|
let paginationTotalRenderer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
paginationTotalRenderer = jest.fn();
|
paginationTotalRenderer = jest.fn(() => <div />);
|
||||||
const props = createMockProps({ showTotal: true, paginationTotalRenderer });
|
const props = createMockProps({ showTotal: true, paginationTotalRenderer });
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
wrapper = render(<Pagination { ...props } />);
|
||||||
wrapper.render();
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render PaginationTotal', () => {
|
it('should not render PaginationTotal', () => {
|
||||||
expect(wrapper.dive().find(PaginationTotal)).toHaveLength(0);
|
expect(wrapper.find('.react-bootstrap-table-pagination-total')).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call props.paginationTotalRenderer correctly', () => {
|
it('should call props.paginationTotalRenderer correctly', () => {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,9 +2,15 @@
|
|||||||
|
|
||||||
`react-bootstrap-table2` support some additional features in [`react-bootstrap-table2-toolkit`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/develop/packages/react-bootstrap-table2-toolkit).
|
`react-bootstrap-table2` support some additional features in [`react-bootstrap-table2-toolkit`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/develop/packages/react-bootstrap-table2-toolkit).
|
||||||
|
|
||||||
In the future, this toolkit will support other feature like row delete, insert etc. Right now we only support Table Search and CSV export.
|
In the future, this toolkit will support other feature like row delete, insert etc. Right now we only following features:
|
||||||
|
|
||||||
|
* Table Search
|
||||||
|
* Export CSV
|
||||||
|
* Column Toggle
|
||||||
|
|
||||||
**[Live Demo For Table Search](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Table%20Search)**
|
**[Live Demo For Table Search](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Table%20Search)**
|
||||||
|
**[Live Demo For Export CSV](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Export%20CSV&selectedStory=Basic%20Export%20CSV)**
|
||||||
|
**[Live Demo For Column Toggle](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Column%20Toggle&selectedStory=Basic%20Column%20Toggle)**
|
||||||
|
|
||||||
**[API&Props Definitation](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html)**
|
**[API&Props Definitation](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html)**
|
||||||
|
|
||||||
@@ -61,6 +67,19 @@ const { SearchBar } = Search;
|
|||||||
|
|
||||||
3. You should render `SearchBar` with `searchProps` as well. The position of `SearchBar` is depends on you.
|
3. You should render `SearchBar` with `searchProps` as well. The position of `SearchBar` is depends on you.
|
||||||
|
|
||||||
|
### `SearchBar` Props
|
||||||
|
#### className - [string]
|
||||||
|
Custom the class on input element.
|
||||||
|
|
||||||
|
#### placeholder - [string]
|
||||||
|
Custom the placeholder on input element.
|
||||||
|
|
||||||
|
#### style - [object]
|
||||||
|
Custom the style on input element.
|
||||||
|
|
||||||
|
#### delay = [number]
|
||||||
|
milionsecond for debounce user input.
|
||||||
|
|
||||||
### Search Options
|
### Search Options
|
||||||
|
|
||||||
#### defaultSearch - [string]
|
#### defaultSearch - [string]
|
||||||
@@ -95,8 +114,36 @@ 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.
|
||||||
@@ -142,4 +189,43 @@ Default is `true`.
|
|||||||
Default is `true`. `false` will only export current data which display on table.
|
Default is `true`. `false` will only export current data which display on table.
|
||||||
|
|
||||||
#### onlyExportSelection - [bool]
|
#### onlyExportSelection - [bool]
|
||||||
Default is `false`. `true` will only export the data which is selected.
|
Default is `false`. `true` will only export the data which is selected.
|
||||||
|
|
||||||
|
#### onlyExportFiltered - [bool]
|
||||||
|
Default is `false`. `true` will only export the data which is filtered/searched.
|
||||||
|
|
||||||
|
>> When you configure this prop as true, you must turn off `exportAll`.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Column Toggle
|
||||||
|
|
||||||
|
Let's see how to render the column toggle in your react component:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ToggleList { ...props.columnToggleProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
> `columnToggleProps` props have enough information to let you custom the toggle list: [demo]([Live Demo For Export CSV](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Export%20CSV&selectedStory=Custom%20Column%20Toggle))
|
||||||
|
|
||||||
|
If you want to have default visibility on specified column, you can just give `true` or `false` on `column.hidden`.
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
|
/* eslint no-param-reassign: 0 */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import statelessDrcorator from './statelessOp';
|
import statelessDecorator from './statelessOp';
|
||||||
|
|
||||||
import createContext from './src/search/context';
|
import createSearchContext from './src/search/context';
|
||||||
|
|
||||||
const ToolkitContext = React.createContext();
|
const ToolkitContext = React.createContext();
|
||||||
|
|
||||||
class ToolkitProvider extends statelessDrcorator(React.Component) {
|
class ToolkitProvider extends statelessDecorator(React.Component) {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
keyField: PropTypes.string.isRequired,
|
keyField: PropTypes.string.isRequired,
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
@@ -29,6 +30,7 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
ignoreHeader: PropTypes.bool,
|
ignoreHeader: PropTypes.bool,
|
||||||
noAutoBOM: PropTypes.bool,
|
noAutoBOM: PropTypes.bool,
|
||||||
exportAll: PropTypes.bool,
|
exportAll: PropTypes.bool,
|
||||||
|
onlyExportFiltered: PropTypes.bool,
|
||||||
onlyExportSelection: PropTypes.bool
|
onlyExportSelection: PropTypes.bool
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
@@ -42,12 +44,22 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
const state = {};
|
||||||
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.onColumnToggle = this.onColumnToggle.bind(this);
|
||||||
this.setDependencyModules = this.setDependencyModules.bind(this);
|
this.setDependencyModules = this.setDependencyModules.bind(this);
|
||||||
|
|
||||||
|
if (props.columnToggle) {
|
||||||
|
state.columnToggle = props.columns
|
||||||
|
.reduce((obj, column) => {
|
||||||
|
obj[column.dataField] = !column.hidden;
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
state.searchText = typeof props.search === 'object' ? (props.search.defaultSearch || '') : '';
|
||||||
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch(searchText) {
|
onSearch(searchText) {
|
||||||
@@ -56,6 +68,18 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClear() {
|
||||||
|
this.setState({ searchText: '' });
|
||||||
|
}
|
||||||
|
|
||||||
|
onColumnToggle(dataField) {
|
||||||
|
const { columnToggle } = this.state;
|
||||||
|
columnToggle[dataField] = !columnToggle[dataField];
|
||||||
|
this.setState(({
|
||||||
|
...this.state,
|
||||||
|
columnToggle
|
||||||
|
}));
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {*} _
|
* @param {*} _
|
||||||
@@ -79,19 +103,30 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
|||||||
};
|
};
|
||||||
if (this.props.search) {
|
if (this.props.search) {
|
||||||
baseProps.search = {
|
baseProps.search = {
|
||||||
searchContext: createContext(this.props.search),
|
searchContext: createSearchContext(this.props.search),
|
||||||
searchText: this.state.searchText
|
searchText: this.state.searchText
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (this.props.columnToggle) {
|
||||||
|
baseProps.columnToggle = {
|
||||||
|
toggles: this.state.columnToggle
|
||||||
|
};
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<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
|
||||||
},
|
},
|
||||||
|
columnToggleProps: {
|
||||||
|
columns: this.props.columns,
|
||||||
|
toggles: this.state.columnToggle,
|
||||||
|
onColumnToggle: this.onColumnToggle
|
||||||
|
},
|
||||||
baseProps
|
baseProps
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ export default ToolkitProvider;
|
|||||||
export const ToolkitContext = Context;
|
export const ToolkitContext = Context;
|
||||||
export { default as Search } from './src/search';
|
export { default as Search } from './src/search';
|
||||||
export { default as CSVExport } from './src/csv';
|
export { default as CSVExport } from './src/csv';
|
||||||
|
export { default as ColumnToggle } from './src/column-toggle';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-toolkit",
|
"name": "react-bootstrap-table2-toolkit",
|
||||||
"version": "1.1.2",
|
"version": "1.4.0",
|
||||||
"description": "The toolkit for react-bootstrap-table2",
|
"description": "The toolkit for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
3
packages/react-bootstrap-table2-toolkit/src/column-toggle/index.js
vendored
Normal file
3
packages/react-bootstrap-table2-toolkit/src/column-toggle/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import ToggleList from './toggle-list';
|
||||||
|
|
||||||
|
export default { ToggleList };
|
||||||
50
packages/react-bootstrap-table2-toolkit/src/column-toggle/toggle-list.js
vendored
Normal file
50
packages/react-bootstrap-table2-toolkit/src/column-toggle/toggle-list.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const ToggleList = ({
|
||||||
|
columns,
|
||||||
|
onColumnToggle,
|
||||||
|
toggles,
|
||||||
|
contextual,
|
||||||
|
className,
|
||||||
|
btnClassName
|
||||||
|
}) => (
|
||||||
|
<div className={ `btn-group btn-group-toggle ${className}` } data-toggle="buttons">
|
||||||
|
{
|
||||||
|
columns
|
||||||
|
.map(column => ({
|
||||||
|
...column,
|
||||||
|
toggle: toggles[column.dataField]
|
||||||
|
}))
|
||||||
|
.map(column => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
key={ column.dataField }
|
||||||
|
className={ `${btnClassName} btn btn-${contextual} ${column.toggle ? 'active' : ''}` }
|
||||||
|
data-toggle="button"
|
||||||
|
aria-pressed={ column.toggle ? 'true' : 'false' }
|
||||||
|
onClick={ () => onColumnToggle(column.dataField) }
|
||||||
|
>
|
||||||
|
{ column.text }
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
ToggleList.propTypes = {
|
||||||
|
columns: PropTypes.array.isRequired,
|
||||||
|
toggles: PropTypes.object.isRequired,
|
||||||
|
onColumnToggle: PropTypes.func.isRequired,
|
||||||
|
btnClassName: PropTypes.string,
|
||||||
|
className: PropTypes.string,
|
||||||
|
contextual: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
ToggleList.defaultProps = {
|
||||||
|
btnClassName: '',
|
||||||
|
className: '',
|
||||||
|
contextual: 'primary'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ToggleList;
|
||||||
@@ -5,12 +5,14 @@ const ExportCSVButton = (props) => {
|
|||||||
const {
|
const {
|
||||||
onExport,
|
onExport,
|
||||||
children,
|
children,
|
||||||
|
className,
|
||||||
...rest
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
className={ `react-bs-table-csv-btn btn btn-default ${className}` }
|
||||||
onClick={ () => onExport() }
|
onClick={ () => onExport() }
|
||||||
{ ...rest }
|
{ ...rest }
|
||||||
>
|
>
|
||||||
@@ -26,7 +28,7 @@ ExportCSVButton.propTypes = {
|
|||||||
style: PropTypes.object
|
style: PropTypes.object
|
||||||
};
|
};
|
||||||
ExportCSVButton.defaultProps = {
|
ExportCSVButton.defaultProps = {
|
||||||
className: 'react-bs-table-csv-btn btn btn-default',
|
className: '',
|
||||||
style: {}
|
style: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,19 +27,24 @@ export default Base =>
|
|||||||
data = source;
|
data = source;
|
||||||
} else if (options.exportAll) {
|
} else if (options.exportAll) {
|
||||||
data = this.props.data;
|
data = this.props.data;
|
||||||
|
} else if (options.onlyExportFiltered) {
|
||||||
|
const payload = {};
|
||||||
|
this.tableExposedAPIEmitter.emit('get.filtered.rows', payload);
|
||||||
|
data = payload.result;
|
||||||
} else {
|
} else {
|
||||||
const payload = {};
|
const payload = {};
|
||||||
this.tableExposedAPIEmitter.emit('get.table.data', payload);
|
this.tableExposedAPIEmitter.emit('get.table.data', payload);
|
||||||
data = payload.result;
|
data = payload.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter data
|
// filter data by row selection
|
||||||
if (options.onlyExportSelection) {
|
if (options.onlyExportSelection) {
|
||||||
const payload = {};
|
const payload = {};
|
||||||
this.tableExposedAPIEmitter.emit('get.selected.rows', payload);
|
this.tableExposedAPIEmitter.emit('get.selected.rows', payload);
|
||||||
const selections = payload.result;
|
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);
|
||||||
save(content, options);
|
save(content, 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,
|
||||||
|
|||||||
23
packages/react-bootstrap-table2-toolkit/src/search/clear-button.js
vendored
Normal file
23
packages/react-bootstrap-table2-toolkit/src/search/clear-button.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const ClearButton = ({
|
||||||
|
onClear,
|
||||||
|
text,
|
||||||
|
className
|
||||||
|
}) => (
|
||||||
|
<button className={ `btn btn-default ${className}` } onClick={ onClear }>{ text }</button>
|
||||||
|
);
|
||||||
|
|
||||||
|
ClearButton.propTypes = {
|
||||||
|
onClear: PropTypes.func.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
|
text: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
ClearButton.defaultProps = {
|
||||||
|
text: 'Clear',
|
||||||
|
className: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClearButton;
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
/* 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 */
|
||||||
|
/* eslint class-methods-use-this: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
@@ -17,36 +19,59 @@ 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);
|
||||||
|
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);
|
||||||
|
this.triggerListener(result);
|
||||||
|
this.setState({
|
||||||
|
data: result
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isRemoteSearch()) {
|
||||||
|
this.setState({ data: nextProps.data });
|
||||||
|
} else if (!_.isEqual(nextProps.data, this.props.data)) {
|
||||||
|
const result = this.search(nextProps);
|
||||||
|
this.triggerListener(result);
|
||||||
|
this.setState({
|
||||||
|
data: result
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
search() {
|
getSearched() {
|
||||||
const { data, columns } = this.props;
|
return this.state.data;
|
||||||
let { searchText } = this.props;
|
}
|
||||||
|
|
||||||
if (isRemoteSearch()) {
|
triggerListener(result) {
|
||||||
if (this.performRemoteSearch) {
|
if (this.props.dataChangeListener) {
|
||||||
handleRemoteSearchChange(searchText);
|
this.props.dataChangeListener.emit('filterChanged', result.length);
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
searchText = searchText.toLowerCase();
|
search(props) {
|
||||||
|
const { data, columns } = props;
|
||||||
|
const searchText = props.searchText.toLowerCase();
|
||||||
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 +94,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 };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table-next",
|
"name": "react-bootstrap-table-next",
|
||||||
"version": "2.0.1",
|
"version": "3.1.0",
|
||||||
"description": "Next generation of react-bootstrap-table",
|
"description": "Next generation of react-bootstrap-table",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"classnames": "2.2.5",
|
"classnames": "2.2.5",
|
||||||
|
"react-transition-group": "2.5.3",
|
||||||
"underscore": "1.9.1"
|
"underscore": "1.9.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
41
packages/react-bootstrap-table2/src/body.js
vendored
41
packages/react-bootstrap-table2/src/body.js
vendored
@@ -15,9 +15,35 @@ 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,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectRowEnabled) {
|
||||||
|
RowComponent = withRowSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellEdit.createContext) {
|
||||||
|
RowComponent = cellEdit.withRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
||||||
|
}
|
||||||
|
this.RowComponent = RowComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -46,21 +72,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 +105,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,8 +7,10 @@ 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) {
|
||||||
@@ -63,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 (
|
||||||
@@ -98,6 +102,15 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
rowClasses={ rowClasses }
|
rowClasses={ rowClasses }
|
||||||
rowEvents={ rowEvents }
|
rowEvents={ rowEvents }
|
||||||
/>
|
/>
|
||||||
|
{hasFooter && (
|
||||||
|
<Footer
|
||||||
|
data={ this.getData() }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
className={ this.props.footerClasses }
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -168,6 +181,7 @@ BootstrapTable.propTypes = {
|
|||||||
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
|
||||||
|
|||||||
3
packages/react-bootstrap-table2/src/cell.js
vendored
3
packages/react-bootstrap-table2/src/cell.js
vendored
@@ -23,7 +23,10 @@ class Cell extends eventDelegater(Component) {
|
|||||||
|
|
||||||
if (shouldUpdate) return true;
|
if (shouldUpdate) return true;
|
||||||
|
|
||||||
|
// if (nextProps.formatter)
|
||||||
|
|
||||||
shouldUpdate =
|
shouldUpdate =
|
||||||
|
(nextProps.column.formatter ? !_.isEqual(this.props.row, nextProps.row) : false) ||
|
||||||
this.props.column.hidden !== nextProps.column.hidden ||
|
this.props.column.hidden !== nextProps.column.hidden ||
|
||||||
this.props.rowIndex !== nextProps.rowIndex ||
|
this.props.rowIndex !== nextProps.rowIndex ||
|
||||||
this.props.columnIndex !== nextProps.columnIndex ||
|
this.props.columnIndex !== nextProps.columnIndex ||
|
||||||
|
|||||||
39
packages/react-bootstrap-table2/src/contexts/column-context.js
vendored
Normal file
39
packages/react-bootstrap-table2/src/contexts/column-context.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const ColumnManagementContext = React.createContext();
|
||||||
|
|
||||||
|
class ColumnManagementProvider extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
columns: PropTypes.array.isRequired,
|
||||||
|
toggles: PropTypes.object
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
toggles: null
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let toggleColumn;
|
||||||
|
const { columns, toggles } = this.props;
|
||||||
|
if (toggles) {
|
||||||
|
toggleColumn = columns.filter(column => toggles[column.dataField]);
|
||||||
|
} else {
|
||||||
|
toggleColumn = columns.filter(column => !column.hidden);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ColumnManagementContext.Provider value={ { columns: toggleColumn } }>
|
||||||
|
{ this.props.children }
|
||||||
|
</ColumnManagementContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
Provider: ColumnManagementProvider,
|
||||||
|
Consumer: ColumnManagementContext.Consumer
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -5,6 +5,7 @@ import React, { Component } from 'react';
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import _ from '../utils';
|
import _ from '../utils';
|
||||||
import createDataContext from './data-context';
|
import createDataContext from './data-context';
|
||||||
|
import createColumnMgtContext from './column-context';
|
||||||
import createSortContext from './sort-context';
|
import createSortContext from './sort-context';
|
||||||
import SelectionContext from './selection-context';
|
import SelectionContext from './selection-context';
|
||||||
import RowExpandContext from './row-expand-context';
|
import RowExpandContext from './row-expand-context';
|
||||||
@@ -22,6 +23,15 @@ const withContext = Base =>
|
|||||||
const exposedAPIEmitter = new EventEmitter();
|
const exposedAPIEmitter = new EventEmitter();
|
||||||
exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData());
|
exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData());
|
||||||
exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected());
|
exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected());
|
||||||
|
exposedAPIEmitter.on('get.filtered.rows', (payload) => {
|
||||||
|
if (this.searchContext) {
|
||||||
|
payload.result = this.searchContext.getSearched();
|
||||||
|
} else if (this.filterContext) {
|
||||||
|
payload.result = this.filterContext.getFiltered();
|
||||||
|
} else {
|
||||||
|
payload.result = this.table.getData();
|
||||||
|
}
|
||||||
|
});
|
||||||
props.registerExposedAPI(exposedAPIEmitter);
|
props.registerExposedAPI(exposedAPIEmitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +40,13 @@ const withContext = Base =>
|
|||||||
dataOperator, this.isRemoteSort, this.handleRemoteSortChange);
|
dataOperator, this.isRemoteSort, this.handleRemoteSortChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
props.columnToggle ||
|
||||||
|
props.columns.filter(col => col.hidden).length > 0
|
||||||
|
) {
|
||||||
|
this.ColumnManagementContext = createColumnMgtContext();
|
||||||
|
}
|
||||||
|
|
||||||
if (props.selectRow) {
|
if (props.selectRow) {
|
||||||
this.SelectionContext = SelectionContext;
|
this.SelectionContext = SelectionContext;
|
||||||
}
|
}
|
||||||
@@ -83,6 +100,7 @@ const withContext = Base =>
|
|||||||
searchProps,
|
searchProps,
|
||||||
sortProps,
|
sortProps,
|
||||||
paginationProps,
|
paginationProps,
|
||||||
|
columnToggleProps
|
||||||
) => (
|
) => (
|
||||||
<Base
|
<Base
|
||||||
ref={ n => this.table = n }
|
ref={ n => this.table = n }
|
||||||
@@ -91,11 +109,40 @@ const withContext = Base =>
|
|||||||
{ ...filterProps }
|
{ ...filterProps }
|
||||||
{ ...searchProps }
|
{ ...searchProps }
|
||||||
{ ...paginationProps }
|
{ ...paginationProps }
|
||||||
|
{ ...columnToggleProps }
|
||||||
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderWithColumnManagementCtx(base, baseProps) {
|
||||||
|
return (
|
||||||
|
rootProps,
|
||||||
|
filterProps,
|
||||||
|
searchProps,
|
||||||
|
sortProps,
|
||||||
|
paginationProps
|
||||||
|
) => (
|
||||||
|
<this.ColumnManagementContext.Provider
|
||||||
|
{ ...baseProps }
|
||||||
|
toggles={ this.props.columnToggle ? this.props.columnToggle.toggles : null }
|
||||||
|
>
|
||||||
|
<this.ColumnManagementContext.Consumer>
|
||||||
|
{
|
||||||
|
columnToggleProps => base(
|
||||||
|
rootProps,
|
||||||
|
filterProps,
|
||||||
|
searchProps,
|
||||||
|
sortProps,
|
||||||
|
paginationProps,
|
||||||
|
columnToggleProps
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</this.ColumnManagementContext.Consumer>
|
||||||
|
</this.ColumnManagementContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderWithSelectionCtx(base, baseProps) {
|
renderWithSelectionCtx(base, baseProps) {
|
||||||
return (
|
return (
|
||||||
rootProps,
|
rootProps,
|
||||||
@@ -217,6 +264,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>
|
||||||
{
|
{
|
||||||
@@ -237,6 +285,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>
|
||||||
{
|
{
|
||||||
@@ -254,6 +303,7 @@ const withContext = Base =>
|
|||||||
return rootProps => (
|
return rootProps => (
|
||||||
<this.CellEditContext.Provider
|
<this.CellEditContext.Provider
|
||||||
{ ...baseProps }
|
{ ...baseProps }
|
||||||
|
ref={ n => this.cellEditContext = n }
|
||||||
selectRow={ this.props.selectRow }
|
selectRow={ this.props.selectRow }
|
||||||
cellEdit={ this.props.cellEdit }
|
cellEdit={ this.props.cellEdit }
|
||||||
data={ rootProps.getData() }
|
data={ rootProps.getData() }
|
||||||
@@ -269,6 +319,10 @@ const withContext = Base =>
|
|||||||
|
|
||||||
let base = this.renderBase();
|
let base = this.renderBase();
|
||||||
|
|
||||||
|
if (this.ColumnManagementContext) {
|
||||||
|
base = this.renderWithColumnManagementCtx(base, baseProps);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.SelectionContext) {
|
if (this.SelectionContext) {
|
||||||
base = this.renderWithSelectionCtx(base, baseProps);
|
base = this.renderWithSelectionCtx(base, baseProps);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,18 +10,31 @@ class RowExpandProvider extends React.Component {
|
|||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
keyField: PropTypes.string.isRequired
|
keyField: PropTypes.string.isRequired
|
||||||
}
|
};
|
||||||
|
|
||||||
state = { expanded: this.props.expandRow.expanded || [] };
|
state = { expanded: this.props.expandRow.expanded || [],
|
||||||
|
isClosing: this.props.expandRow.isClosing || [] };
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.expandRow) {
|
if (nextProps.expandRow) {
|
||||||
|
const isClosing = this.state.expanded.reduce((acc, cur) => {
|
||||||
|
if (!nextProps.expandRow.expanded.includes(cur)) {
|
||||||
|
acc.push(cur);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
this.setState(() => ({ expanded: nextProps.expandRow.expanded, isClosing }));
|
||||||
|
} else {
|
||||||
this.setState(() => ({
|
this.setState(() => ({
|
||||||
expanded: nextProps.expandRow.expanded || this.state.expanded
|
expanded: this.state.expanded
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClosed = (closedRow) => {
|
||||||
|
this.setState({ isClosing: this.state.isClosing.filter(value => value !== closedRow) });
|
||||||
|
};
|
||||||
|
|
||||||
handleRowExpand = (rowKey, expanded, rowIndex, e) => {
|
handleRowExpand = (rowKey, expanded, rowIndex, e) => {
|
||||||
const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props;
|
const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props;
|
||||||
if (nonExpandable && nonExpandable.includes(rowKey)) {
|
if (nonExpandable && nonExpandable.includes(rowKey)) {
|
||||||
@@ -29,11 +42,15 @@ class RowExpandProvider extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currExpanded = [...this.state.expanded];
|
let currExpanded = [...this.state.expanded];
|
||||||
|
let isClosing = [...this.state.isClosing];
|
||||||
|
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
if (onlyOneExpanding) currExpanded = [rowKey];
|
if (onlyOneExpanding) {
|
||||||
else currExpanded.push(rowKey);
|
isClosing = isClosing.concat(currExpanded);
|
||||||
|
currExpanded = [rowKey];
|
||||||
|
} else currExpanded.push(rowKey);
|
||||||
} else {
|
} else {
|
||||||
|
isClosing.push(rowKey);
|
||||||
currExpanded = currExpanded.filter(value => value !== rowKey);
|
currExpanded = currExpanded.filter(value => value !== rowKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,8 +58,8 @@ class RowExpandProvider extends React.Component {
|
|||||||
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||||
onExpand(row, expanded, rowIndex, e);
|
onExpand(row, expanded, rowIndex, e);
|
||||||
}
|
}
|
||||||
this.setState(() => ({ expanded: currExpanded }));
|
this.setState(() => ({ expanded: currExpanded, isClosing }));
|
||||||
}
|
};
|
||||||
|
|
||||||
handleAllRowExpand = (e, expandAll) => {
|
handleAllRowExpand = (e, expandAll) => {
|
||||||
const {
|
const {
|
||||||
@@ -68,7 +85,7 @@ class RowExpandProvider extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState(() => ({ expanded: currExpanded }));
|
this.setState(() => ({ expanded: currExpanded }));
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { data, keyField } = this.props;
|
const { data, keyField } = this.props;
|
||||||
@@ -78,6 +95,8 @@ class RowExpandProvider extends React.Component {
|
|||||||
...this.props.expandRow,
|
...this.props.expandRow,
|
||||||
nonExpandable: this.props.expandRow.nonExpandable,
|
nonExpandable: this.props.expandRow.nonExpandable,
|
||||||
expanded: this.state.expanded,
|
expanded: this.state.expanded,
|
||||||
|
isClosing: this.state.isClosing,
|
||||||
|
onClosed: this.onClosed,
|
||||||
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
|
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
|
||||||
onRowExpand: this.handleRowExpand,
|
onRowExpand: this.handleRowExpand,
|
||||||
onAllRowExpand: this.handleAllRowExpand
|
onAllRowExpand: this.handleAllRowExpand
|
||||||
|
|||||||
@@ -14,26 +14,27 @@ class SelectionProvider extends React.Component {
|
|||||||
keyField: PropTypes.string.isRequired
|
keyField: PropTypes.string.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
state = { selected: this.props.selectRow.selected || [] };
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.selected = props.selectRow.selected || [];
|
||||||
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.selectRow) {
|
if (nextProps.selectRow) {
|
||||||
this.setState(() => ({
|
this.selected = nextProps.selectRow.selected || this.selected;
|
||||||
selected: nextProps.selectRow.selected || this.state.selected
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// exposed API
|
// exposed API
|
||||||
getSelected() {
|
getSelected() {
|
||||||
return this.state.selected;
|
return this.selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRowSelect = (rowKey, checked, rowIndex, e) => {
|
handleRowSelect = (rowKey, checked, rowIndex, e) => {
|
||||||
const { data, keyField, selectRow: { mode, onSelect } } = this.props;
|
const { data, keyField, selectRow: { mode, onSelect } } = this.props;
|
||||||
const { ROW_SELECT_SINGLE } = Const;
|
const { ROW_SELECT_SINGLE } = Const;
|
||||||
|
|
||||||
let currSelected = [...this.state.selected];
|
let currSelected = [...this.selected];
|
||||||
|
|
||||||
let result = true;
|
let result = true;
|
||||||
if (onSelect) {
|
if (onSelect) {
|
||||||
@@ -41,18 +42,17 @@ class SelectionProvider extends React.Component {
|
|||||||
result = onSelect(row, checked, rowIndex, e);
|
result = onSelect(row, checked, rowIndex, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(() => {
|
if (result === true || result === undefined) {
|
||||||
if (result === true || result === undefined) {
|
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
currSelected = [rowKey];
|
||||||
currSelected = [rowKey];
|
} else if (checked) { // when select mode is checkbox
|
||||||
} else if (checked) { // when select mode is checkbox
|
currSelected.push(rowKey);
|
||||||
currSelected.push(rowKey);
|
} else {
|
||||||
} else {
|
currSelected = currSelected.filter(value => value !== rowKey);
|
||||||
currSelected = currSelected.filter(value => value !== rowKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { selected: currSelected };
|
}
|
||||||
});
|
this.selected = currSelected;
|
||||||
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAllRowsSelect = (e, isUnSelect) => {
|
handleAllRowsSelect = (e, isUnSelect) => {
|
||||||
@@ -64,7 +64,7 @@ class SelectionProvider extends React.Component {
|
|||||||
nonSelectable
|
nonSelectable
|
||||||
}
|
}
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { selected } = this.state;
|
const { selected } = this;
|
||||||
|
|
||||||
let currSelected;
|
let currSelected;
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ class SelectionProvider extends React.Component {
|
|||||||
dataOperator.getSelectedRows(
|
dataOperator.getSelectedRows(
|
||||||
data,
|
data,
|
||||||
keyField,
|
keyField,
|
||||||
isUnSelect ? this.state.selected : currSelected
|
isUnSelect ? selected : currSelected
|
||||||
),
|
),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
@@ -89,7 +89,8 @@ class SelectionProvider extends React.Component {
|
|||||||
currSelected = result;
|
currSelected = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState(() => ({ selected: currSelected }));
|
this.selected = currSelected;
|
||||||
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -99,7 +100,7 @@ class SelectionProvider extends React.Component {
|
|||||||
} = getSelectionSummary(
|
} = getSelectionSummary(
|
||||||
this.props.data,
|
this.props.data,
|
||||||
this.props.keyField,
|
this.props.keyField,
|
||||||
this.state.selected
|
this.selected
|
||||||
);
|
);
|
||||||
|
|
||||||
let checkedStatus;
|
let checkedStatus;
|
||||||
@@ -113,7 +114,7 @@ class SelectionProvider extends React.Component {
|
|||||||
<SelectionContext.Provider
|
<SelectionContext.Provider
|
||||||
value={ {
|
value={ {
|
||||||
...this.props.selectRow,
|
...this.props.selectRow,
|
||||||
selected: this.state.selected,
|
selected: this.selected,
|
||||||
onRowSelect: this.handleRowSelect,
|
onRowSelect: this.handleRowSelect,
|
||||||
onAllRowsSelect: this.handleAllRowsSelect,
|
onAllRowsSelect: this.handleAllRowsSelect,
|
||||||
allRowsSelected,
|
allRowsSelected,
|
||||||
|
|||||||
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;
|
||||||
64
packages/react-bootstrap-table2/src/footer.js
vendored
Normal file
64
packages/react-bootstrap-table2/src/footer.js
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Const from './const';
|
||||||
|
import FooterCell from './footer-cell';
|
||||||
|
import _ from './utils';
|
||||||
|
|
||||||
|
const Footer = (props) => {
|
||||||
|
const { data, className, columns, selectRow, expandRow } = props;
|
||||||
|
const SelectionFooterCellComp = () => <th />;
|
||||||
|
const ExpansionFooterCellComp = () => <th />;
|
||||||
|
|
||||||
|
const isRenderExpandColumnInLeft = (
|
||||||
|
expandColumnPosition = Const.INDICATOR_POSITION_LEFT
|
||||||
|
) => expandColumnPosition === Const.INDICATOR_POSITION_LEFT;
|
||||||
|
|
||||||
|
const childrens = columns.map((column, i) => {
|
||||||
|
if (column.footer === undefined || column.footer === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnData = _.pluck(data, column.dataField);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FooterCell
|
||||||
|
index={ i }
|
||||||
|
key={ column.dataField }
|
||||||
|
column={ column }
|
||||||
|
columnData={ columnData }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectRow && selectRow.hideSelectColumn !== true) {
|
||||||
|
childrens.unshift(<SelectionFooterCellComp key="selection" />);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expandRow.showExpandColumn) {
|
||||||
|
if (isRenderExpandColumnInLeft(expandRow.expandColumnPosition)) {
|
||||||
|
childrens.unshift(<ExpansionFooterCellComp key="expansion" />);
|
||||||
|
} else {
|
||||||
|
childrens.push(<ExpansionFooterCellComp key="expansion" />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tfoot>
|
||||||
|
<tr className={ className }>
|
||||||
|
{ childrens }
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Footer.propTypes = {
|
||||||
|
data: PropTypes.array,
|
||||||
|
className: PropTypes.string,
|
||||||
|
columns: PropTypes.array,
|
||||||
|
selectRow: PropTypes.object,
|
||||||
|
expandRow: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
31
packages/react-bootstrap-table2/src/header.js
vendored
31
packages/react-bootstrap-table2/src/header.js
vendored
@@ -39,24 +39,21 @@ const Header = (props) => {
|
|||||||
|
|
||||||
const childrens = [
|
const childrens = [
|
||||||
columns.map((column, i) => {
|
columns.map((column, i) => {
|
||||||
if (!column.hidden) {
|
const currSort = column.dataField === sortField;
|
||||||
const currSort = column.dataField === sortField;
|
const isLastSorting = column.dataField === sortField;
|
||||||
const isLastSorting = column.dataField === sortField;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HeaderCell
|
<HeaderCell
|
||||||
index={ i }
|
index={ i }
|
||||||
key={ column.dataField }
|
key={ column.dataField }
|
||||||
column={ column }
|
column={ column }
|
||||||
onSort={ onSort }
|
onSort={ onSort }
|
||||||
sorting={ currSort }
|
sorting={ currSort }
|
||||||
onFilter={ onFilter }
|
onFilter={ onFilter }
|
||||||
onExternalFilter={ onExternalFilter }
|
onExternalFilter={ onExternalFilter }
|
||||||
sortOrder={ sortOrder }
|
sortOrder={ sortOrder }
|
||||||
isLastSorting={ isLastSorting }
|
isLastSorting={ isLastSorting }
|
||||||
/>);
|
/>);
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,37 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
|
||||||
const ExpandRow = ({ children, ...rest }) => (
|
const ExpandRow = ({ children, expanded, onClosed, ...rest }) => (
|
||||||
<tr className="expanding-row">
|
<tr>
|
||||||
<td { ...rest }>{ children }</td>
|
<td className="reset-expansion-style" { ...rest }>
|
||||||
|
<CSSTransition
|
||||||
|
appear
|
||||||
|
in={ expanded }
|
||||||
|
timeout={ 400 }
|
||||||
|
classNames="row-expand-slide"
|
||||||
|
onExited={ onClosed }
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div className="row-expansion-style">
|
||||||
|
{ children }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CSSTransition>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
||||||
ExpandRow.propTypes = {
|
ExpandRow.propTypes = {
|
||||||
children: PropTypes.node
|
children: PropTypes.node,
|
||||||
|
expanded: PropTypes.bool,
|
||||||
|
onClosed: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
ExpandRow.defaultProps = {
|
ExpandRow.defaultProps = {
|
||||||
children: null
|
children: null,
|
||||||
|
expanded: false,
|
||||||
|
onClosed: null
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ExpandRow;
|
export default ExpandRow;
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import React from 'react';
|
|||||||
import ExpandRow from './expand-row';
|
import ExpandRow from './expand-row';
|
||||||
import ExpansionContext from '../contexts/row-expand-context';
|
import ExpansionContext from '../contexts/row-expand-context';
|
||||||
|
|
||||||
export default (Component, visibleColumnSize) => {
|
export default (Component) => {
|
||||||
const renderWithExpansion = (props, expandRow) => {
|
const renderWithExpansion = (props, expandRow) => {
|
||||||
const key = props.value;
|
const key = props.value;
|
||||||
|
|
||||||
const expanded = expandRow.expanded.includes(key);
|
const expanded = expandRow.expanded.includes(key);
|
||||||
|
const isClosing = expandRow.isClosing.includes(key);
|
||||||
const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key);
|
const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
<Component
|
<Component
|
||||||
{ ...props }
|
{ ...props }
|
||||||
@@ -18,9 +18,11 @@ export default (Component, visibleColumnSize) => {
|
|||||||
expandable={ expandable }
|
expandable={ expandable }
|
||||||
expandRow={ { ...expandRow } }
|
expandRow={ { ...expandRow } }
|
||||||
/>,
|
/>,
|
||||||
expanded ? <ExpandRow
|
expanded || isClosing ? <ExpandRow
|
||||||
key={ `${key}-expanding` }
|
key={ `${key}-expanding` }
|
||||||
colSpan={ visibleColumnSize }
|
colSpan={ props.visibleColumnSize }
|
||||||
|
expanded={ expanded }
|
||||||
|
onClosed={ () => expandRow.onClosed(key) }
|
||||||
>
|
>
|
||||||
{ expandRow.renderer(props.row) }
|
{ expandRow.renderer(props.row) }
|
||||||
</ExpandRow> : null
|
</ExpandRow> : null
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export default class SelectionCell extends Component {
|
|||||||
selected,
|
selected,
|
||||||
disabled,
|
disabled,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
rowIndex,
|
||||||
selectionRenderer
|
selectionRenderer
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@@ -78,7 +79,8 @@ export default class SelectionCell extends Component {
|
|||||||
selectionRenderer ? selectionRenderer({
|
selectionRenderer ? selectionRenderer({
|
||||||
mode: inputType,
|
mode: inputType,
|
||||||
checked: selected,
|
checked: selected,
|
||||||
disabled
|
disabled,
|
||||||
|
rowIndex
|
||||||
}) : (
|
}) : (
|
||||||
<input
|
<input
|
||||||
type={ inputType }
|
type={ inputType }
|
||||||
|
|||||||
@@ -33,92 +33,89 @@ export default class RowPureContent extends React.Component {
|
|||||||
let tabIndex = tabIndexStart;
|
let tabIndex = tabIndexStart;
|
||||||
|
|
||||||
return columns.map((column, index) => {
|
return columns.map((column, index) => {
|
||||||
if (!column.hidden) {
|
const { dataField } = column;
|
||||||
const { dataField } = column;
|
const content = _.get(row, dataField);
|
||||||
const content = _.get(row, dataField);
|
if (rowIndex === editingRowIdx && index === editingColIdx) {
|
||||||
if (rowIndex === editingRowIdx && index === editingColIdx) {
|
|
||||||
return (
|
|
||||||
<EditingCellComponent
|
|
||||||
key={ `${content}-${index}-editing` }
|
|
||||||
row={ row }
|
|
||||||
rowIndex={ rowIndex }
|
|
||||||
column={ column }
|
|
||||||
columnIndex={ index }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// render cell
|
|
||||||
let cellTitle;
|
|
||||||
let cellStyle = {};
|
|
||||||
let cellAttrs = {
|
|
||||||
..._.isFunction(column.attrs)
|
|
||||||
? column.attrs(content, row, rowIndex, index)
|
|
||||||
: column.attrs
|
|
||||||
};
|
|
||||||
|
|
||||||
if (column.events) {
|
|
||||||
const events = Object.assign({}, column.events);
|
|
||||||
Object.keys(Object.assign({}, column.events)).forEach((key) => {
|
|
||||||
const originFn = events[key];
|
|
||||||
events[key] = (...rest) => originFn(...rest, row, rowIndex);
|
|
||||||
});
|
|
||||||
cellAttrs = { ...cellAttrs, ...events };
|
|
||||||
}
|
|
||||||
|
|
||||||
const cellClasses = _.isFunction(column.classes)
|
|
||||||
? column.classes(content, row, rowIndex, index)
|
|
||||||
: column.classes;
|
|
||||||
|
|
||||||
if (column.style) {
|
|
||||||
cellStyle = _.isFunction(column.style)
|
|
||||||
? column.style(content, row, rowIndex, index)
|
|
||||||
: column.style;
|
|
||||||
cellStyle = Object.assign({}, cellStyle) || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (column.title) {
|
|
||||||
cellTitle = _.isFunction(column.title)
|
|
||||||
? column.title(content, row, rowIndex, index)
|
|
||||||
: content;
|
|
||||||
cellAttrs.title = cellTitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (column.align) {
|
|
||||||
cellStyle.textAlign =
|
|
||||||
_.isFunction(column.align)
|
|
||||||
? column.align(content, row, rowIndex, index)
|
|
||||||
: column.align;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellClasses) cellAttrs.className = cellClasses;
|
|
||||||
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
|
||||||
|
|
||||||
let editableCell = _.isDefined(column.editable) ? column.editable : true;
|
|
||||||
if (column.dataField === keyField || !editable) editableCell = false;
|
|
||||||
if (_.isFunction(column.editable)) {
|
|
||||||
editableCell = column.editable(content, row, rowIndex, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tabIndexStart !== -1) {
|
|
||||||
cellAttrs.tabIndex = tabIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Cell
|
<EditingCellComponent
|
||||||
key={ `${content}-${index}` }
|
key={ `${content}-${index}-editing` }
|
||||||
row={ row }
|
row={ row }
|
||||||
editable={ editableCell }
|
|
||||||
rowIndex={ rowIndex }
|
rowIndex={ rowIndex }
|
||||||
columnIndex={ index }
|
|
||||||
column={ column }
|
column={ column }
|
||||||
onStart={ onStart }
|
columnIndex={ index }
|
||||||
clickToEdit={ clickToEdit }
|
|
||||||
dbclickToEdit={ dbclickToEdit }
|
|
||||||
{ ...cellAttrs }
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
// render cell
|
||||||
|
let cellTitle;
|
||||||
|
let cellStyle = {};
|
||||||
|
let cellAttrs = {
|
||||||
|
..._.isFunction(column.attrs)
|
||||||
|
? column.attrs(content, row, rowIndex, index)
|
||||||
|
: column.attrs
|
||||||
|
};
|
||||||
|
|
||||||
|
if (column.events) {
|
||||||
|
const events = Object.assign({}, column.events);
|
||||||
|
Object.keys(Object.assign({}, column.events)).forEach((key) => {
|
||||||
|
const originFn = events[key];
|
||||||
|
events[key] = (...rest) => originFn(...rest, row, rowIndex);
|
||||||
|
});
|
||||||
|
cellAttrs = { ...cellAttrs, ...events };
|
||||||
|
}
|
||||||
|
|
||||||
|
const cellClasses = _.isFunction(column.classes)
|
||||||
|
? column.classes(content, row, rowIndex, index)
|
||||||
|
: column.classes;
|
||||||
|
|
||||||
|
if (column.style) {
|
||||||
|
cellStyle = _.isFunction(column.style)
|
||||||
|
? column.style(content, row, rowIndex, index)
|
||||||
|
: column.style;
|
||||||
|
cellStyle = Object.assign({}, cellStyle) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.title) {
|
||||||
|
cellTitle = _.isFunction(column.title)
|
||||||
|
? column.title(content, row, rowIndex, index)
|
||||||
|
: content;
|
||||||
|
cellAttrs.title = cellTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.align) {
|
||||||
|
cellStyle.textAlign =
|
||||||
|
_.isFunction(column.align)
|
||||||
|
? column.align(content, row, rowIndex, index)
|
||||||
|
: column.align;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellClasses) cellAttrs.className = cellClasses;
|
||||||
|
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||||
|
|
||||||
|
let editableCell = _.isDefined(column.editable) ? column.editable : true;
|
||||||
|
if (column.dataField === keyField || !editable) editableCell = false;
|
||||||
|
if (_.isFunction(column.editable)) {
|
||||||
|
editableCell = column.editable(content, row, rowIndex, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tabIndexStart !== -1) {
|
||||||
|
cellAttrs.tabIndex = tabIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Cell
|
||||||
|
key={ `${content}-${index}` }
|
||||||
|
row={ row }
|
||||||
|
editable={ editableCell }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
columnIndex={ index }
|
||||||
|
column={ column }
|
||||||
|
onStart={ onStart }
|
||||||
|
clickToEdit={ clickToEdit }
|
||||||
|
dbclickToEdit={ dbclickToEdit }
|
||||||
|
{ ...cellAttrs }
|
||||||
|
/>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ export default ExtendBase =>
|
|||||||
return (
|
return (
|
||||||
nextProps.editingRowIdx === nextProps.rowIndex ||
|
nextProps.editingRowIdx === nextProps.rowIndex ||
|
||||||
(this.props.editingRowIdx === nextProps.rowIndex &&
|
(this.props.editingRowIdx === nextProps.rowIndex &&
|
||||||
nextProps.editingRowIdx === null)
|
nextProps.editingRowIdx === null) ||
|
||||||
|
this.props.editingRowIdx === nextProps.rowIndex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ export default ExtendBase =>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.props.columns.length; i += 1) {
|
for (let i = 0; i < this.props.columns.length; i += 1) {
|
||||||
if (this.props.columns[i].hidden !== nextProps.columns[i].hidden) {
|
if (!_.isEqual(this.props.columns[i], nextProps.columns[i])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,10 +68,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.expanding-row {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.react-bootstrap-table-editing-cell {
|
td.react-bootstrap-table-editing-cell {
|
||||||
.animated {
|
.animated {
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
@@ -161,4 +157,26 @@
|
|||||||
animation-name: bounceOut;
|
animation-name: bounceOut;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.reset-expansion-style{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.row-expansion-style{
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
.row-expand-slide-appear{
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.row-expand-slide-appear-active{
|
||||||
|
max-height: 1000px;
|
||||||
|
transition: max-height 3s linear;
|
||||||
|
}
|
||||||
|
.row-expand-slide-exit{
|
||||||
|
max-height: 1000px;
|
||||||
|
}
|
||||||
|
.row-expand-slide-exit-active{
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: max-height 400ms cubic-bezier(0, 0.95, 0, 0.95)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -218,6 +218,47 @@ describe('Cell', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when props.row is change', () => {
|
||||||
|
describe('and column.formatter is enable', () => {
|
||||||
|
const column = { dataField: 'name', text: 'Product Name', formatter: () => 123 };
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
row,
|
||||||
|
columnIndex: 1,
|
||||||
|
rowIndex: 1,
|
||||||
|
tabIndex: 5,
|
||||||
|
column
|
||||||
|
};
|
||||||
|
wrapper = shallow(
|
||||||
|
<Cell { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true', () => {
|
||||||
|
nextProps = { ...props, row: { ...row, alert: 'test' } };
|
||||||
|
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('but column.formatter is disable', () => {
|
||||||
|
const column = { dataField: 'name', text: 'Product Name' };
|
||||||
|
beforeEach(() => {
|
||||||
|
props = {
|
||||||
|
row,
|
||||||
|
columnIndex: 1,
|
||||||
|
rowIndex: 1,
|
||||||
|
tabIndex: 5,
|
||||||
|
column
|
||||||
|
};
|
||||||
|
wrapper = shallow(
|
||||||
|
<Cell { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true', () => {
|
||||||
|
nextProps = { ...props, row: { ...row, alert: 'test' } };
|
||||||
|
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('if column.isDummyField is true', () => {
|
describe('if column.isDummyField is true', () => {
|
||||||
describe('when content is change', () => {
|
describe('when content is change', () => {
|
||||||
const column = { dataField: '', text: 'Product Name', isDummyField: true };
|
const column = { dataField: '', text: 'Product Name', isDummyField: true };
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
|
import BootstrapTable from '../../src/bootstrap-table';
|
||||||
|
import createColumnManagementContext from '../../src/contexts/column-context';
|
||||||
|
|
||||||
|
describe('ColumnManagementContext', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const data = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'A'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'B'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Name'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const mockBase = jest.fn((props => (
|
||||||
|
<BootstrapTable
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
keyField="id"
|
||||||
|
{ ...props }
|
||||||
|
/>
|
||||||
|
)));
|
||||||
|
|
||||||
|
const ColumnManagementContext = createColumnManagementContext();
|
||||||
|
|
||||||
|
function shallowContext(options = {}) {
|
||||||
|
return (
|
||||||
|
<ColumnManagementContext.Provider
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...options }
|
||||||
|
>
|
||||||
|
<ColumnManagementContext.Consumer>
|
||||||
|
{
|
||||||
|
columnToggleProps => mockBase(columnToggleProps)
|
||||||
|
}
|
||||||
|
</ColumnManagementContext.Consumer>
|
||||||
|
</ColumnManagementContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('default render', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext());
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct Provider property after calling createColumnManagementContext', () => {
|
||||||
|
expect(ColumnManagementContext.Provider).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct Consumer property after calling createColumnManagementContext', () => {
|
||||||
|
expect(ColumnManagementContext.Consumer).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when toggles props exist', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext({
|
||||||
|
toggles: {
|
||||||
|
id: true,
|
||||||
|
name: false
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render component with correct columns props', () => {
|
||||||
|
expect(wrapper.prop('value').columns).toHaveLength(columns.length - 1);
|
||||||
|
expect(wrapper.prop('value').columns[0].dataField).toEqual('id');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if there is any column.hidden is true', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext({
|
||||||
|
columns: [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Name',
|
||||||
|
hidden: true
|
||||||
|
}]
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render component with correct columns props', () => {
|
||||||
|
expect(wrapper.prop('value').columns).toHaveLength(columns.length - 1);
|
||||||
|
expect(wrapper.prop('value').columns[0].dataField).toEqual('id');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -47,6 +47,7 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render correctly', () => {
|
it('should render correctly', () => {
|
||||||
@@ -77,6 +78,57 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if thers\'s any column hidden', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const columnsWithHidden = [{
|
||||||
|
dataField: keyField,
|
||||||
|
text: 'ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Name',
|
||||||
|
hidden: true
|
||||||
|
}];
|
||||||
|
wrapper = shallow(
|
||||||
|
<BootstrapTable keyField={ keyField } data={ data } columns={ columnsWithHidden } />
|
||||||
|
);
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create contexts correctly', () => {
|
||||||
|
expect(wrapper.instance().DataContext).toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).toBeDefined();
|
||||||
|
expect(wrapper.instance().SelectionContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if columnToggle is enable', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const columnToggle = { toggles: { id: true, name: true } };
|
||||||
|
wrapper = shallow(
|
||||||
|
<BootstrapTable
|
||||||
|
keyField={ keyField }
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
columnToggle={ columnToggle }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create contexts correctly', () => {
|
||||||
|
expect(wrapper.instance().DataContext).toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).toBeDefined();
|
||||||
|
expect(wrapper.instance().SelectionContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,6 +153,7 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -134,6 +187,7 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).toBeDefined();
|
expect(wrapper.instance().CellEditContext).toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -163,6 +217,7 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -193,6 +248,7 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).toBeDefined();
|
expect(wrapper.instance().FilterContext).toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
expect(wrapper.instance().PaginationContext).not.toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -223,6 +279,7 @@ describe('Context', () => {
|
|||||||
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
expect(wrapper.instance().CellEditContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
expect(wrapper.instance().FilterContext).not.toBeDefined();
|
||||||
expect(wrapper.instance().PaginationContext).toBeDefined();
|
expect(wrapper.instance().PaginationContext).toBeDefined();
|
||||||
|
expect(wrapper.instance().ColumnManagementContext).not.toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -73,15 +73,15 @@ describe('DataContext', () => {
|
|||||||
expect(SelectionContext.Consumer).toBeDefined();
|
expect(SelectionContext.Consumer).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct state.data', () => {
|
it('should have correct this.selected', () => {
|
||||||
expect(wrapper.state().selected).toEqual([]);
|
expect(wrapper.instance().selected).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should pass correct sort props to children element', () => {
|
it('should pass correct sort props to children element', () => {
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
expect(mockBase).toHaveBeenCalledWith({
|
expect(mockBase).toHaveBeenCalledWith({
|
||||||
...defaultSelectRow,
|
...defaultSelectRow,
|
||||||
selected: wrapper.state().selected,
|
selected: wrapper.instance().selected,
|
||||||
onRowSelect: wrapper.instance().handleRowSelect,
|
onRowSelect: wrapper.instance().handleRowSelect,
|
||||||
onAllRowsSelect: wrapper.instance().handleAllRowsSelect,
|
onAllRowsSelect: wrapper.instance().handleAllRowsSelect,
|
||||||
allRowsNotSelected: true,
|
allRowsNotSelected: true,
|
||||||
@@ -104,8 +104,8 @@ describe('DataContext', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct state.selected', () => {
|
it('should have correct this.selected', () => {
|
||||||
expect(wrapper.state().selected).toEqual(newSelectRow.selected);
|
expect(wrapper.instance().selected).toEqual(newSelectRow.selected);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if nextProps.selectRow is not existing', () => {
|
describe('if nextProps.selectRow is not existing', () => {
|
||||||
@@ -120,8 +120,8 @@ describe('DataContext', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should keep origin state.selected', () => {
|
it('should keep origin this.selected', () => {
|
||||||
expect(wrapper.state().selected).toEqual(defaultSelected);
|
expect(wrapper.instance().selected).toEqual(defaultSelected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -131,8 +131,8 @@ describe('DataContext', () => {
|
|||||||
wrapper.instance().componentWillReceiveProps({});
|
wrapper.instance().componentWillReceiveProps({});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not set state.selected', () => {
|
it('should not set this.selected', () => {
|
||||||
expect(wrapper.state().selected).toEqual([]);
|
expect(wrapper.instance().selected).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -148,8 +148,8 @@ describe('DataContext', () => {
|
|||||||
wrapper = shallow(shallowContext(selectRow));
|
wrapper = shallow(shallowContext(selectRow));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct state.data', () => {
|
it('should have correct this.selected', () => {
|
||||||
expect(wrapper.state().selected).toEqual(selectRow.selected);
|
expect(wrapper.instance().selected).toEqual(selectRow.selected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -164,12 +164,12 @@ describe('DataContext', () => {
|
|||||||
wrapper = shallow(shallowContext(selectRow));
|
wrapper = shallow(shallowContext(selectRow));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set state.selected correctly', () => {
|
it('should set this.selected correctly', () => {
|
||||||
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
|
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
|
||||||
expect(wrapper.state('selected')).toEqual([firstSelectedRow]);
|
expect(wrapper.instance().selected).toEqual([firstSelectedRow]);
|
||||||
|
|
||||||
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
|
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
|
||||||
expect(wrapper.state('selected')).toEqual([secondSelectedRow]);
|
expect(wrapper.instance().selected).toEqual([secondSelectedRow]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -178,18 +178,19 @@ describe('DataContext', () => {
|
|||||||
wrapper = shallow(shallowContext());
|
wrapper = shallow(shallowContext());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set state.selected correctly', () => {
|
it('should set this.selected correctly', () => {
|
||||||
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
|
wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex);
|
||||||
expect(wrapper.state('selected')).toEqual(expect.arrayContaining([firstSelectedRow]));
|
expect(wrapper.instance().selected).toEqual(expect.arrayContaining([firstSelectedRow]));
|
||||||
|
|
||||||
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
|
wrapper.instance().handleRowSelect(secondSelectedRow, true, rowIndex);
|
||||||
expect(wrapper.state('selected')).toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow]));
|
expect(wrapper.instance().selected)
|
||||||
|
.toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow]));
|
||||||
|
|
||||||
wrapper.instance().handleRowSelect(firstSelectedRow, false, rowIndex);
|
wrapper.instance().handleRowSelect(firstSelectedRow, false, rowIndex);
|
||||||
expect(wrapper.state('selected')).toEqual(expect.arrayContaining([secondSelectedRow]));
|
expect(wrapper.instance().selected).toEqual(expect.arrayContaining([secondSelectedRow]));
|
||||||
|
|
||||||
wrapper.instance().handleRowSelect(secondSelectedRow, false, rowIndex);
|
wrapper.instance().handleRowSelect(secondSelectedRow, false, rowIndex);
|
||||||
expect(wrapper.state('selected')).toEqual([]);
|
expect(wrapper.instance().selected).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -220,8 +221,8 @@ describe('DataContext', () => {
|
|||||||
wrapper.instance().handleAllRowsSelect(e, false);
|
wrapper.instance().handleAllRowsSelect(e, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set state.selected correctly', () => {
|
it('should set this.selected correctly', () => {
|
||||||
expect(wrapper.state('selected')).toEqual(data.map(d => d[keyField]));
|
expect(wrapper.instance().selected).toEqual(data.map(d => d[keyField]));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when selectRow.onSelectAll is defined', () => {
|
describe('when selectRow.onSelectAll is defined', () => {
|
||||||
@@ -237,7 +238,7 @@ describe('DataContext', () => {
|
|||||||
it('should call selectRow.onSelectAll correctly', () => {
|
it('should call selectRow.onSelectAll correctly', () => {
|
||||||
expect(onSelectAll).toHaveBeenCalledWith(
|
expect(onSelectAll).toHaveBeenCalledWith(
|
||||||
true,
|
true,
|
||||||
dataOperator.getSelectedRows(data, keyField, wrapper.state('selected')),
|
dataOperator.getSelectedRows(data, keyField, wrapper.instance().selected),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -253,8 +254,8 @@ describe('DataContext', () => {
|
|||||||
wrapper.instance().handleAllRowsSelect(e, true);
|
wrapper.instance().handleAllRowsSelect(e, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set state.selected correctly', () => {
|
it('should set this.selected correctly', () => {
|
||||||
expect(wrapper.state('selected')).toEqual([]);
|
expect(wrapper.instance().selected).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when selectRow.onSelectAll is defined', () => {
|
describe('when selectRow.onSelectAll is defined', () => {
|
||||||
|
|||||||
124
packages/react-bootstrap-table2/test/footer.test.js
Normal file
124
packages/react-bootstrap-table2/test/footer.test.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow, render } from 'enzyme';
|
||||||
|
|
||||||
|
import Const from '../src/const';
|
||||||
|
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 selectRow = {
|
||||||
|
mode: Const.ROW_SELECT_DISABLED,
|
||||||
|
selected: [],
|
||||||
|
hideSelectColumn: true
|
||||||
|
};
|
||||||
|
const expandRow = {
|
||||||
|
renderer: undefined,
|
||||||
|
expanded: [],
|
||||||
|
nonExpandable: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const keyField = 'id';
|
||||||
|
|
||||||
|
describe('simplest footer', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(
|
||||||
|
<Footer
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
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 }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find(`.${className}`).length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when selecrRow prop is enable', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = render(
|
||||||
|
<Footer
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ { ...selectRow, mode: 'radio', hideSelectColumn: false } }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('th').length).toBe(columns.length + 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when expandRow prop is enable', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = render(
|
||||||
|
<Footer
|
||||||
|
data={ data }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
expandRow={ { expandRow, showExpandColumn: true } }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.find('th').length).toBe(columns.length + 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user