mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 21:50:07 +00:00
Compare commits
166 Commits
react-boot
...
react-boot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c0fc2748c | ||
|
|
973ece8b39 | ||
|
|
0a94f3ce39 | ||
|
|
0ca8e54ce2 | ||
|
|
69d534e26c | ||
|
|
c2a30cb716 | ||
|
|
83dc888d17 | ||
|
|
41da9afbcb | ||
|
|
91816fcc01 | ||
|
|
620309115f | ||
|
|
297f3e0c4f | ||
|
|
d42a10bbae | ||
|
|
5c52412542 | ||
|
|
a5f74cecfe | ||
|
|
a30a8fd96b | ||
|
|
424dbea270 | ||
|
|
b261c33e37 | ||
|
|
7dbdc1943b | ||
|
|
d4be1675db | ||
|
|
d3161f02eb | ||
|
|
28ba6d5677 | ||
|
|
4ddbfd4972 | ||
|
|
d84dc46ff1 | ||
|
|
e0163625d4 | ||
|
|
24ab58a464 | ||
|
|
6e19368733 | ||
|
|
bc4697bf95 | ||
|
|
9d2a6a1b23 | ||
|
|
bb752fcec8 | ||
|
|
aedd1f5942 | ||
|
|
5a5f10f609 | ||
|
|
e041a3d736 | ||
|
|
f175fd4186 | ||
|
|
5a6b7e122d | ||
|
|
a7ae524c49 | ||
|
|
a23599f52f | ||
|
|
c50853b16d | ||
|
|
3f74542c98 | ||
|
|
47aa41b8fa | ||
|
|
67ed2e6c80 | ||
|
|
794a97956d | ||
|
|
78ca01bb1a | ||
|
|
b79dbc80f6 | ||
|
|
3f21a67620 | ||
|
|
9e3ae385ce | ||
|
|
c6ea19fe8a | ||
|
|
a5b42dca92 | ||
|
|
28f3c33db3 | ||
|
|
2530a70c00 | ||
|
|
569dd61463 | ||
|
|
68264b45ce | ||
|
|
e251068657 | ||
|
|
e4fbb284b4 | ||
|
|
a6afc9d9a8 | ||
|
|
a0ba41c103 | ||
|
|
4a16cb314d | ||
|
|
98a04a5710 | ||
|
|
c22a2a1d71 | ||
|
|
9bc25c9d3e | ||
|
|
4554db02d2 | ||
|
|
b7fac973d2 | ||
|
|
6925358631 | ||
|
|
27c3cdab29 | ||
|
|
bc0c048735 | ||
|
|
a4c1090a0f | ||
|
|
5fac4540a1 | ||
|
|
f7a06401ae | ||
|
|
858ad9543b | ||
|
|
abf618ce6d | ||
|
|
ea6cb78302 | ||
|
|
bacbfdbbf0 | ||
|
|
465212ff35 | ||
|
|
2a58f99a97 | ||
|
|
7bda61f5be | ||
|
|
7220b2d073 | ||
|
|
f7a1c91904 | ||
|
|
ea827bfeb5 | ||
|
|
f1f4bd784d | ||
|
|
569c22ba49 | ||
|
|
b1e5c0cb20 | ||
|
|
7ee38a647f | ||
|
|
01ec19344d | ||
|
|
19be67c914 | ||
|
|
ae4d38cae6 | ||
|
|
81a6428a03 | ||
|
|
166affc4c1 | ||
|
|
d0fb46e39f | ||
|
|
828844a1e9 | ||
|
|
774293b76d | ||
|
|
e77cbdb2df | ||
|
|
ef2f828572 | ||
|
|
15731932cf | ||
|
|
dd54294382 | ||
|
|
185c184f01 | ||
|
|
d45345ed10 | ||
|
|
dda8460017 | ||
|
|
6735536fd8 | ||
|
|
95623bbb5f | ||
|
|
9567c7829d | ||
|
|
8499991c41 | ||
|
|
1e76ca9bdb | ||
|
|
fa13550d8c | ||
|
|
709d59ce62 | ||
|
|
66329ecdbf | ||
|
|
ee6cec5a2d | ||
|
|
52fc84899b | ||
|
|
8c10867b8c | ||
|
|
640ada7659 | ||
|
|
73a5c34535 | ||
|
|
2879cf891e | ||
|
|
994ed2e395 | ||
|
|
4b790e4bec | ||
|
|
21e7c3a53a | ||
|
|
6fce0d7066 | ||
|
|
154f1c91c3 | ||
|
|
02d78e5104 | ||
|
|
41cc6b01af | ||
|
|
bd410e7303 | ||
|
|
eced3eef1f | ||
|
|
ca5a41a8b3 | ||
|
|
7a31729ebb | ||
|
|
3a8faf8170 | ||
|
|
532581bb6e | ||
|
|
c228b229d2 | ||
|
|
10adbf472c | ||
|
|
a6e2f0f8f8 | ||
|
|
f1d93853ec | ||
|
|
bb7243c5db | ||
|
|
3ea816b2e6 | ||
|
|
b268c4e0cd | ||
|
|
8b8f336878 | ||
|
|
8517248aee | ||
|
|
ae0cd8a32f | ||
|
|
51c82cdfb3 | ||
|
|
8e087329b3 | ||
|
|
ee2885d055 | ||
|
|
901307e471 | ||
|
|
4ff5be706a | ||
|
|
f8a3fedbb2 | ||
|
|
0bf5831b4e | ||
|
|
dd0b8c6b0f | ||
|
|
8f028d9dd4 | ||
|
|
2c68f22646 | ||
|
|
02d566bb32 | ||
|
|
2b12045017 | ||
|
|
0cdf086d56 | ||
|
|
d4fa9a84e3 | ||
|
|
c84fc84b9e | ||
|
|
ad8cdde513 | ||
|
|
db19e7dd9b | ||
|
|
33b36e5108 | ||
|
|
7209441eb6 | ||
|
|
7a1ed67847 | ||
|
|
eaf9f4cd39 | ||
|
|
f0d85520c0 | ||
|
|
0e2862baa5 | ||
|
|
5ac058c489 | ||
|
|
ac38d2f28e | ||
|
|
591abaae6e | ||
|
|
b76566126c | ||
|
|
687583536a | ||
|
|
d136ec3197 | ||
|
|
37db43f5a7 | ||
|
|
a966900752 | ||
|
|
3b1fc3a559 | ||
|
|
849d9af8c4 |
43
README.md
43
README.md
@@ -1,43 +1,52 @@
|
|||||||
# react-bootstrap-table2
|
# react-bootstrap-table2
|
||||||
|
|
||||||
[](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2)
|
[](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2)
|
||||||
Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
|
Rebuilt of [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
|
||||||
|
|
||||||
> `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to some guys already used it
|
> Note that `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to the name being already taken.
|
||||||
|
|
||||||
`react-bootstrap-table2` separate some functionalities from core modules to other modules like following:
|
`react-bootstrap-table2` separates some functionalities from its core modules to other modules as listed in the following:
|
||||||
|
|
||||||
* [`react-bootstrap-table-next`](https://www.npmjs.com/package/react-bootstrap-table-next)
|
- [`react-bootstrap-table-next`](https://www.npmjs.com/package/react-bootstrap-table-next)
|
||||||
* [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter)
|
- [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter)
|
||||||
* [`react-bootstrap-table2-editor`](https://www.npmjs.com/package/react-bootstrap-table2-editor)
|
- [`react-bootstrap-table2-editor`](https://www.npmjs.com/package/react-bootstrap-table2-editor)
|
||||||
* [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator)
|
- [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator)
|
||||||
* [`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)
|
||||||
* [`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)
|
||||||
|
|
||||||
This can help your application with less bundled size and also help us have clean design to avoid handling to much logic in kernal module(SRP).
|
Not only does this reduce the bundle size of your apps but also helps us have a cleaner design to avoid handling too much logic in the kernel module(SRP).
|
||||||
|
|
||||||
## Migration
|
## Migration
|
||||||
If you are the user from legacy [`react-bootstrap-table`](https://github.com/AllenFang/react-bootstrap-table/), please have a look on [this](./docs/migration.md).
|
|
||||||
|
If you are coming from the legacy [`react-bootstrap-table`](https://github.com/AllenFang/react-bootstrap-table/), please check out the [migration guide](./docs/migration.md).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html).
|
See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html).
|
||||||
|
|
||||||
## Online Demo
|
## Online Demo
|
||||||
|
|
||||||
See `react-bootstrap-table2` [storybook](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html).
|
See `react-bootstrap-table2` [storybook](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html).
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
See [release plans](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/release-plan.html).
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
Please check [development guide](./docs/development.md).
|
|
||||||
|
|
||||||
## How should I run storybook example in my local?
|
Please check the [development guide](./docs/development.md).
|
||||||
|
|
||||||
|
## Running storybook example on your local machine
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
# Clone the repo
|
||||||
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
||||||
|
|
||||||
|
# change dir to the cloned repo
|
||||||
$ cd react-bootstrap-table2
|
$ cd react-bootstrap-table2
|
||||||
|
|
||||||
|
# Install all dependencies with yarn
|
||||||
$ yarn install
|
$ yarn install
|
||||||
|
|
||||||
|
# Start the stroybook server, then go to localhost:6006
|
||||||
$ yarn storybook
|
$ yarn storybook
|
||||||
$ Go to localhost:6006
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Storybook examples: [`packages/react-bootstrap-table2-example/examples`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/master/packages/react-bootstrap-table2-example/examples)**
|
**Storybook examples: [`packages/react-bootstrap-table2-example/examples`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/master/packages/react-bootstrap-table2-example/examples)**
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
* [hover](#hover)
|
* [hover](#hover)
|
||||||
* [condensed](#condensed)
|
* [condensed](#condensed)
|
||||||
* [id](#id)
|
* [id](#id)
|
||||||
|
* [tabIndexCell](#tabIndexCell)
|
||||||
* [classes](#classes)
|
* [classes](#classes)
|
||||||
* [wrapperClasses](#wrapperClasses)
|
* [wrapperClasses](#wrapperClasses)
|
||||||
* [headerClasses](#headerClasses)
|
* [headerClasses](#headerClasses)
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
* [rowStyle](#rowStyle)
|
* [rowStyle](#rowStyle)
|
||||||
* [rowClasses](#rowClasses)
|
* [rowClasses](#rowClasses)
|
||||||
* [rowEvents](#rowEvents)
|
* [rowEvents](#rowEvents)
|
||||||
|
* [hiddenRows](#hiddenRows)
|
||||||
* [defaultSorted](#defaultSorted)
|
* [defaultSorted](#defaultSorted)
|
||||||
* [defaultSortDirection](#defaultSortDirection)
|
* [defaultSortDirection](#defaultSortDirection)
|
||||||
* [pagination](#pagination)
|
* [pagination](#pagination)
|
||||||
@@ -112,6 +114,10 @@ Same as bootstrap `.table-condensed` class for making a table more compact by cu
|
|||||||
|
|
||||||
### <a name='id'>id - [String]</a>
|
### <a name='id'>id - [String]</a>
|
||||||
Customize id on `table` element.
|
Customize id on `table` element.
|
||||||
|
|
||||||
|
### <a name='tabIndexCell'>tabIndexCell - [Bool]</a>
|
||||||
|
Enable the `tabIndex` attribute on `<td>` element.
|
||||||
|
|
||||||
### <a name='classes'>classes - [String]</a>
|
### <a name='classes'>classes - [String]</a>
|
||||||
Customize class on `table` element.
|
Customize class on `table` element.
|
||||||
|
|
||||||
@@ -176,6 +182,14 @@ const rowEvents = {
|
|||||||
<BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } />
|
<BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } />
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <a name='hiddenRows'>hiddenRows - [Array]</a>
|
||||||
|
Hide rows, this props accept an array of row keys:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const hiddenRows = [1, 4];
|
||||||
|
<BootstrapTable data={ data } columns={ columns } hiddenRows={ hiddenRows } />
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='defaultSorted'>defaultSorted - [Array]</a>
|
### <a name='defaultSorted'>defaultSorted - [Array]</a>
|
||||||
`defaultSorted` accept an object array which allow you to define the default sort columns when first render.
|
`defaultSorted` accept an object array which allow you to define the default sort columns when first render.
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ $ npm install react-bootstrap-table2-editor --save
|
|||||||
* [blurToSave](#blurToSave)
|
* [blurToSave](#blurToSave)
|
||||||
* [nonEditableRows](#nonEditableRows)
|
* [nonEditableRows](#nonEditableRows)
|
||||||
* [timeToCloseMessage](#timeToCloseMessage)
|
* [timeToCloseMessage](#timeToCloseMessage)
|
||||||
|
* [autoSelectText](#autoSelectText)
|
||||||
* [beforeSaveCell](#beforeSaveCell)
|
* [beforeSaveCell](#beforeSaveCell)
|
||||||
* [afterSaveCell](#afterSaveCell)
|
* [afterSaveCell](#afterSaveCell)
|
||||||
* [errorMessage](#errorMessage)
|
* [errorMessage](#errorMessage)
|
||||||
@@ -43,6 +44,11 @@ Default is `false`, enable it will be able to save the cell automatically when b
|
|||||||
### <a name='nonEditableRows'>cellEdit.nonEditableRows - [Function]</a>
|
### <a name='nonEditableRows'>cellEdit.nonEditableRows - [Function]</a>
|
||||||
`cellEdit.nonEditableRows` accept a callback function and expect return an array which used to restrict all the columns of some rows as non-editable. So the each item in return array should be rowkey(`keyField`)
|
`cellEdit.nonEditableRows` accept a callback function and expect return an array which used to restrict all the columns of some rows as non-editable. So the each item in return array should be rowkey(`keyField`)
|
||||||
|
|
||||||
|
### <a name='autoSelectText'>cellEdit.autoSelectText - [Bool]</a>
|
||||||
|
Default is false, when enable it, `react-bootstrap-table2` will help you to select the text in the text input automatically when editing.
|
||||||
|
|
||||||
|
> NOTE: This props only work for `text` and `textarea`.
|
||||||
|
|
||||||
### <a name='timeToCloseMessage'>cellEdit.timeToCloseMessage - [Function]</a>
|
### <a name='timeToCloseMessage'>cellEdit.timeToCloseMessage - [Function]</a>
|
||||||
If a [`column.validator`](./columns.md#validator) defined and the new value is invalid, `react-bootstrap-table2` will popup a alert at the bottom of editor. `cellEdit.timeToCloseMessage` is a chance to let you decide how long the alert should be stay. Default is 3000 millisecond.
|
If a [`column.validator`](./columns.md#validator) defined and the new value is invalid, `react-bootstrap-table2` will popup a alert at the bottom of editor. `cellEdit.timeToCloseMessage` is a chance to let you decide how long the alert should be stay. Default is 3000 millisecond.
|
||||||
|
|
||||||
@@ -56,6 +62,24 @@ const cellEdit = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to perform a async `beforeSaveCell`, you can do it like that:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cellEdit: {
|
||||||
|
// omit...
|
||||||
|
beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Do you want to accep this change?')) {
|
||||||
|
done(); // contine to save the changes
|
||||||
|
} else {
|
||||||
|
done(false); // reject the changes
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='afterSaveCell'>cellEdit.afterSaveCell - [Function]</a>
|
### <a name='afterSaveCell'>cellEdit.afterSaveCell - [Function]</a>
|
||||||
This callback function will be called after updating cell.
|
This callback function will be called after updating cell.
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ Available properties in a column object:
|
|||||||
* [text (**required**)](#text)
|
* [text (**required**)](#text)
|
||||||
|
|
||||||
#### Optional
|
#### Optional
|
||||||
|
* [isDummyField](#isDummyField)
|
||||||
* [hidden](#hidden)
|
* [hidden](#hidden)
|
||||||
* [formatter](#formatter)
|
* [formatter](#formatter)
|
||||||
* [formatExtraData](#formatExtraData)
|
* [formatExtraData](#formatExtraData)
|
||||||
* [sort](#sort)
|
* [sort](#sort)
|
||||||
* [sortFunc](#sortFunc)
|
* [sortFunc](#sortFunc)
|
||||||
|
* [sortCaret](#sortCaret)
|
||||||
* [onSort](#onSort)
|
* [onSort](#onSort)
|
||||||
* [classes](#classes)
|
* [classes](#classes)
|
||||||
* [style](#style)
|
* [style](#style)
|
||||||
@@ -84,6 +86,11 @@ dataField: 'address.city'
|
|||||||
## <a name='text'>column.text (**required**) - [String]</a>
|
## <a name='text'>column.text (**required**) - [String]</a>
|
||||||
`text` will be the column text in header column by default, if your header is not only text or you want to customize the header column, please check [`column.headerFormatter`](#headerFormatter)
|
`text` will be the column text in header column by default, if your header is not only text or you want to customize the header column, please check [`column.headerFormatter`](#headerFormatter)
|
||||||
|
|
||||||
|
## <a name='isDummyField'>column.isDummyField - [Bool]</a>
|
||||||
|
Sometime, you just want to have a column which is not perform any data but just some action components. In this situation, we suggest you to use `isDummyField`. If column is dummy, the [`column.dataField`](#dataField) can be any string value, cause of it's meaningless.
|
||||||
|
|
||||||
|
There's only one different for dummy column than normal column, which is dummy column will compare the whole row value instead of cell value when call `shouldComponentUpdate`.
|
||||||
|
|
||||||
## <a name='hidden'>column.hidden - [Bool]</a>
|
## <a name='hidden'>column.hidden - [Bool]</a>
|
||||||
`hidden` allow you to hide column when `true` given.
|
`hidden` allow you to hide column when `true` given.
|
||||||
|
|
||||||
@@ -148,6 +155,20 @@ Enable the column sort via a `true` value given.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## <a name='sortCaret'>column.sortCaret - [Function]</a>
|
||||||
|
Use`column.sortCaret` to custom the sort caret. This callback function accept two arguments: `order` and `column`
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
sort: true,
|
||||||
|
sortCaret: (order, column) => {
|
||||||
|
return //...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
> The possible value of `order` argument is **`asc`**, **`desc`** and **`undefined`**.
|
||||||
|
|
||||||
## <a name='classes'>column.classes - [String | Function]</a>
|
## <a name='classes'>column.classes - [String | Function]</a>
|
||||||
It's available to have custom class on table column:
|
It's available to have custom class on table column:
|
||||||
|
|
||||||
@@ -358,17 +379,27 @@ A new `String` will be the result of element headerAlign.
|
|||||||
|
|
||||||
|
|
||||||
## <a name='events'>column.events - [Object]</a>
|
## <a name='events'>column.events - [Object]</a>
|
||||||
You can assign any [HTML Event](https://www.w3schools.com/tags/ref_eventattributes.asp) on table column via event property:
|
You can assign any [HTML Event](https://www.w3schools.com/tags/ref_eventattributes.asp) on table column via `events` property.
|
||||||
|
|
||||||
|
`react-bootstrap-table2` currently only support following events which will receive some specific information:
|
||||||
|
|
||||||
|
* onClick
|
||||||
|
* onDoubleClick
|
||||||
|
* onMouseEnter
|
||||||
|
* onMouseLeave
|
||||||
|
* onContextMenu
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
// omit...
|
// omit...
|
||||||
events: {
|
events: {
|
||||||
onClick: e => { ... }
|
onClick: (e, column, columnIndex, row, rowIndex) => { ... },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the events is not listed above, the callback function will only pass the `event` object.
|
||||||
|
|
||||||
## <a name='headerEvents'>column.headerEvents - [Object]</a>
|
## <a name='headerEvents'>column.headerEvents - [Object]</a>
|
||||||
`headerEvents` same as [`column.events`](#events) but this is for header column.
|
`headerEvents` same as [`column.events`](#events) but this is for header column.
|
||||||
|
|
||||||
@@ -522,6 +553,28 @@ The return value can be a bool or an object. If your validation is pass, return
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to perform a asycn validation, you can do it like this:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
validator: (newValue, row, column, done) => {
|
||||||
|
settimeout(() => {
|
||||||
|
// async validation ok
|
||||||
|
return done();
|
||||||
|
|
||||||
|
// async validation not ok
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'SOME_REASON_HERE'
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 2000);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## <a name='editCellStyle'>column.editCellStyle - [Object | Function]</a>
|
## <a name='editCellStyle'>column.editCellStyle - [Object | Function]</a>
|
||||||
You can use `column.editCellStyle` to custom the style of `<td>` when cell editing. It like most of customizable functionality, it also accept a callback function with following params:
|
You can use `column.editCellStyle` to custom the style of `<td>` when cell editing. It like most of customizable functionality, it also accept a callback function with following params:
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
### Setup
|
### Setup
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
||||||
$ cd react-bootstrap-table
|
$ cd react-bootstrap-table2
|
||||||
$ npm install
|
$ npm install
|
||||||
$ lerna bootstrap # ./node_modules/.bin/lerna bootstrap
|
$ lerna bootstrap # ./node_modules/.bin/lerna bootstrap
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -113,8 +113,6 @@ Please see [available pagination configurations](https://react-bootstrap-table.g
|
|||||||
|
|
||||||
Remember to install [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator) firstly.
|
Remember to install [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator) firstly.
|
||||||
|
|
||||||
No big changes for pagination, but still can't custom the pagination list, button and sizePerPage dropdown.
|
|
||||||
|
|
||||||
## Table Search
|
## Table Search
|
||||||
The usage of search functionality is a little bit different from legacy search. The mainly different thing is developer have to render the search input field, we do believe it will be very flexible for all the developers who want to custom the search position or search field itself.
|
The usage of search functionality is a little bit different from legacy search. The mainly different thing is developer have to render the search input field, we do believe it will be very flexible for all the developers who want to custom the search position or search field itself.
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
* [onExpand](#onExpand)
|
* [onExpand](#onExpand)
|
||||||
* [onExpandAll](#onExpandAll)
|
* [onExpandAll](#onExpandAll)
|
||||||
* [showExpandColumn](#showExpandColumn)
|
* [showExpandColumn](#showExpandColumn)
|
||||||
|
* [onlyOneExpanding](#onlyOneExpanding)
|
||||||
|
* [expandByColumnOnly](#expandByColumnOnly)
|
||||||
* [expandColumnRenderer](#expandColumnRenderer)
|
* [expandColumnRenderer](#expandColumnRenderer)
|
||||||
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
|
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
|
||||||
|
|
||||||
@@ -90,13 +92,16 @@ const expandRow = {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### <a name='expandColumnRenderer'>expandRow.expandColumnRenderer - [Function]</a>
|
### <a name='expandColumnRenderer'>expandRow.expandColumnRenderer - [Function]</a>
|
||||||
Provide a callback function which allow you to custom the expand indicator. This callback only have one argument which is an object and contain one property `expanded` which indicate if current row is expanded
|
Provide a callback function which allow you to custom the expand indicator. This callback only have one argument which is an object and contain these properties:
|
||||||
|
* `expanded`: If current row is expanded or not
|
||||||
|
* `rowKey`: Current row key
|
||||||
|
* `expandable`: If currnet row is expandable or not
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const expandRow = {
|
const expandRow = {
|
||||||
renderer: (row) => ...
|
renderer: (row) => ...
|
||||||
expandColumnRenderer: ({ expanded }) => (
|
expandColumnRenderer: ({ expanded, rowKey, expandable }) => (
|
||||||
// ....
|
// ....
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@@ -127,3 +132,24 @@ const expandRow = {
|
|||||||
showExpandColumn: true
|
showExpandColumn: true
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <a name='onlyOneExpanding'>expandRow.onlyOneExpanding - [Bool]</a>
|
||||||
|
Default is `false`. Enable this will only allow one row get expand at the same time.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const expandRow = {
|
||||||
|
renderer: (row) => ...
|
||||||
|
onlyOneExpanding: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### <a name='expandByColumnOnly'>expandRow.expandByColumnOnly - [Bool]</a>
|
||||||
|
Default is `false`. If you want to restrict user to expand/collapse row via clicking the expand column only, you can enable it.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const expandRow = {
|
||||||
|
renderer: (row) => ...,
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandByColumnOnly: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|||||||
@@ -12,10 +12,12 @@
|
|||||||
* [bgColor](#bgColor)
|
* [bgColor](#bgColor)
|
||||||
* [nonSelectable)](#nonSelectable)
|
* [nonSelectable)](#nonSelectable)
|
||||||
* [clickToSelect)](#clickToSelect)
|
* [clickToSelect)](#clickToSelect)
|
||||||
|
* [clickToExpand)](#clickToExpand)
|
||||||
* [clickToEdit](#clickToEdit)
|
* [clickToEdit](#clickToEdit)
|
||||||
* [onSelect](#onSelect)
|
* [onSelect](#onSelect)
|
||||||
* [onSelectAll](#onSelectAll)
|
* [onSelectAll](#onSelectAll)
|
||||||
* [hideSelectColumn](#hideSelectColumn)
|
* [hideSelectColumn](#hideSelectColumn)
|
||||||
|
* [hideSelectAll](#hideSelectAll)
|
||||||
* [selectionRenderer](#selectionRenderer)
|
* [selectionRenderer](#selectionRenderer)
|
||||||
* [selectionHeaderRenderer](#selectionHeaderRenderer)
|
* [selectionHeaderRenderer](#selectionHeaderRenderer)
|
||||||
|
|
||||||
@@ -147,6 +149,16 @@ const selectRow = {
|
|||||||
> Note: When you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing
|
> Note: When you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing
|
||||||
> If you want to click on row to select row and edit cell simultaneously, you are suppose to enable [`selectRow.clickToEdit`](#clickToEdit)
|
> If you want to click on row to select row and edit cell simultaneously, you are suppose to enable [`selectRow.clickToEdit`](#clickToEdit)
|
||||||
|
|
||||||
|
### <a name='clickToExpand'>selectRow.clickToExpand - [Bool]</a>
|
||||||
|
Default is false, enable it will let user able to expand and select row when user clicking on the row.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToExpand: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='clickToEdit'>selectRow.clickToEdit - [Bool]</a>
|
### <a name='clickToEdit'>selectRow.clickToEdit - [Bool]</a>
|
||||||
Able to click to edit cell and select row
|
Able to click to edit cell and select row
|
||||||
|
|
||||||
@@ -199,18 +211,44 @@ const selectRow = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> If you want to reject current select action, just return `false`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
onSelect: (row, isSelect, rowIndex, e) => {
|
||||||
|
if (SOME_CONDITION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='onSelectAll'>selectRow.onSelectAll - [Function]</a>
|
### <a name='onSelectAll'>selectRow.onSelectAll - [Function]</a>
|
||||||
This callback function will be called when select/unselect all and it only work when you configure [`selectRow.mode`](#mode) as `checkbox`.
|
This callback function will be called when select/unselect all and it only work when you configure [`selectRow.mode`](#mode) as `checkbox`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const selectRow = {
|
const selectRow = {
|
||||||
mode: 'checkbox',
|
mode: 'checkbox',
|
||||||
onSelectAll: (isSelect, results, e) => {
|
onSelectAll: (isSelect, rows, e) => {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> If you want to control the final selection result, just return a row key array:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
onSelectAll: (isSelect, rows, e) => {
|
||||||
|
if (isSelect && SOME_CONDITION) {
|
||||||
|
return [1, 3, 4]; // finally, key 1, 3, 4 will being selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='hideSelectColumn'>selectRow.hideSelectColumn - [Bool]</a>
|
### <a name='hideSelectColumn'>selectRow.hideSelectColumn - [Bool]</a>
|
||||||
Default is `false`, if you don't want to have a selection column, give this prop as `true`
|
Default is `false`, if you don't want to have a selection column, give this prop as `true`
|
||||||
|
|
||||||
@@ -222,3 +260,13 @@ const selectRow = {
|
|||||||
bgColor: 'red'
|
bgColor: 'red'
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <a name='hideSelectAll'>selectRow.hideSelectAll - [Bool]</a>
|
||||||
|
Default is `false`, if you don't want to render the select all checkbox on the header of selection column, give this prop as `true`!
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
hideSelectAll: true
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import Adapter from 'enzyme-adapter-react-16';
|
import Adapter from 'enzyme-adapter-react-16.3';
|
||||||
import { configure } from 'enzyme';
|
import { configure } from 'enzyme';
|
||||||
|
|
||||||
const configureEnzyme = () => {
|
const configureEnzyme = () => {
|
||||||
|
|||||||
@@ -50,8 +50,8 @@
|
|||||||
"babel-preset-stage-0": "6.24.1",
|
"babel-preset-stage-0": "6.24.1",
|
||||||
"babel-register": "6.24.1",
|
"babel-register": "6.24.1",
|
||||||
"css-loader": "0.28.1",
|
"css-loader": "0.28.1",
|
||||||
"enzyme": "3.3.0",
|
"enzyme": "3.4.0",
|
||||||
"enzyme-adapter-react-16": "1.1.1",
|
"enzyme-adapter-react-16.3": "1.0.0",
|
||||||
"enzyme-to-json": "3.3.4",
|
"enzyme-to-json": "3.3.4",
|
||||||
"eslint": "4.5.0",
|
"eslint": "4.5.0",
|
||||||
"eslint-config-airbnb": "15.1.0",
|
"eslint-config-airbnb": "15.1.0",
|
||||||
@@ -82,8 +82,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"classnames": "2.2.5",
|
"classnames": "2.2.5",
|
||||||
"prop-types": "15.5.10",
|
"prop-types": "15.5.10",
|
||||||
"react": "16.3.2",
|
"react": "16.4.0",
|
||||||
"react-dom": "16.3.2",
|
"react-dom": "16.4.0",
|
||||||
"underscore": "1.9.1"
|
"underscore": "1.9.1"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import createContext from './src/context';
|
import createContext from './src/context';
|
||||||
import editingCellFactory from './src/editing-cell';
|
import withRowLevelCellEdit from './src/row-consumer';
|
||||||
|
import createEditingCell from './src/editing-cell-consumer';
|
||||||
import {
|
import {
|
||||||
EDITTYPE,
|
EDITTYPE,
|
||||||
CLICK_TO_CELL_EDIT,
|
|
||||||
DBCLICK_TO_CELL_EDIT,
|
DBCLICK_TO_CELL_EDIT,
|
||||||
DELAY_FOR_DBCLICK
|
DELAY_FOR_DBCLICK
|
||||||
} from './src/const';
|
} from './src/const';
|
||||||
|
|
||||||
export default (options = {}) => ({
|
export default (options = {}) => ({
|
||||||
createContext,
|
createContext,
|
||||||
editingCellFactory,
|
createEditingCell,
|
||||||
CLICK_TO_CELL_EDIT,
|
withRowLevelCellEdit,
|
||||||
DBCLICK_TO_CELL_EDIT,
|
DBCLICK_TO_CELL_EDIT,
|
||||||
DELAY_FOR_DBCLICK,
|
DELAY_FOR_DBCLICK,
|
||||||
options
|
options
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-editor",
|
"name": "react-bootstrap-table2-editor",
|
||||||
"version": "1.0.0",
|
"version": "1.2.2",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ class CheckBoxEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const { didMount } = this.props;
|
||||||
this.checkbox.focus();
|
this.checkbox.focus();
|
||||||
|
if (didMount) didMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
@@ -28,7 +30,7 @@ class CheckBoxEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { defaultValue, className, ...rest } = this.props;
|
const { defaultValue, didMount, className, ...rest } = this.props;
|
||||||
const editorClass = cs('editor edit-chseckbox checkbox', className);
|
const editorClass = cs('editor edit-chseckbox checkbox', className);
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
@@ -50,12 +52,14 @@ CheckBoxEditor.propTypes = {
|
|||||||
]),
|
]),
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
defaultValue: PropTypes.any,
|
defaultValue: PropTypes.any,
|
||||||
onChange: PropTypes.func
|
onChange: PropTypes.func,
|
||||||
|
didMount: PropTypes.func
|
||||||
};
|
};
|
||||||
CheckBoxEditor.defaultProps = {
|
CheckBoxEditor.defaultProps = {
|
||||||
className: '',
|
className: '',
|
||||||
value: 'on:off',
|
value: 'on:off',
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
onChange: undefined
|
onChange: undefined,
|
||||||
|
didMount: undefined
|
||||||
};
|
};
|
||||||
export default CheckBoxEditor;
|
export default CheckBoxEditor;
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
|
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
|
||||||
|
|
||||||
|
const CellEditContext = React.createContext();
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
_,
|
_,
|
||||||
dataOperator,
|
dataOperator,
|
||||||
isRemoteCellEdit,
|
isRemoteCellEdit,
|
||||||
handleCellChange
|
handleCellChange
|
||||||
) => {
|
) => {
|
||||||
let EditingCell;
|
|
||||||
const CellEditContext = React.createContext();
|
|
||||||
|
|
||||||
class CellEditProvider extends React.Component {
|
class CellEditProvider extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
@@ -23,6 +22,7 @@ export default (
|
|||||||
blurToSave: PropTypes.bool,
|
blurToSave: PropTypes.bool,
|
||||||
beforeSaveCell: PropTypes.func,
|
beforeSaveCell: PropTypes.func,
|
||||||
afterSaveCell: PropTypes.func,
|
afterSaveCell: PropTypes.func,
|
||||||
|
onStartEdit: PropTypes.func,
|
||||||
nonEditableRows: PropTypes.func,
|
nonEditableRows: PropTypes.func,
|
||||||
timeToCloseMessage: PropTypes.number,
|
timeToCloseMessage: PropTypes.number,
|
||||||
errorMessage: PropTypes.any
|
errorMessage: PropTypes.any
|
||||||
@@ -31,7 +31,7 @@ export default (
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
EditingCell = props.cellEdit.editingCellFactory(_);
|
this.doUpdate = this.doUpdate.bind(this);
|
||||||
this.startEditing = this.startEditing.bind(this);
|
this.startEditing = this.startEditing.bind(this);
|
||||||
this.escapeEditing = this.escapeEditing.bind(this);
|
this.escapeEditing = this.escapeEditing.bind(this);
|
||||||
this.completeEditing = this.completeEditing.bind(this);
|
this.completeEditing = this.completeEditing.bind(this);
|
||||||
@@ -56,11 +56,36 @@ export default (
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleCellUpdate(row, column, newValue) {
|
handleCellUpdate(row, column, newValue) {
|
||||||
const { keyField, cellEdit, data } = this.props;
|
const { cellEdit } = this.props;
|
||||||
const { beforeSaveCell, afterSaveCell } = cellEdit.options;
|
const { beforeSaveCell } = cellEdit.options;
|
||||||
const oldValue = _.get(row, column.dataField);
|
const oldValue = _.get(row, column.dataField);
|
||||||
|
const beforeSaveCellDone = (result = true) => {
|
||||||
|
if (result) {
|
||||||
|
this.doUpdate(row, column, newValue);
|
||||||
|
} else {
|
||||||
|
this.escapeEditing();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_.isFunction(beforeSaveCell)) {
|
||||||
|
const result = beforeSaveCell(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
beforeSaveCellDone
|
||||||
|
);
|
||||||
|
if (_.isObject(result) && result.async) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.doUpdate(row, column, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
doUpdate(row, column, newValue) {
|
||||||
|
const { keyField, cellEdit, data } = this.props;
|
||||||
|
const { afterSaveCell } = cellEdit.options;
|
||||||
const rowId = _.get(row, keyField);
|
const rowId = _.get(row, keyField);
|
||||||
if (_.isFunction(beforeSaveCell)) beforeSaveCell(oldValue, newValue, row, column);
|
const oldValue = _.get(row, column.dataField);
|
||||||
if (isRemoteCellEdit()) {
|
if (isRemoteCellEdit()) {
|
||||||
handleCellChange(rowId, column.dataField, newValue);
|
handleCellChange(rowId, column.dataField, newValue);
|
||||||
} else {
|
} else {
|
||||||
@@ -101,8 +126,6 @@ export default (
|
|||||||
const {
|
const {
|
||||||
cellEdit: {
|
cellEdit: {
|
||||||
options: { nonEditableRows, errorMessage, ...optionsRest },
|
options: { nonEditableRows, errorMessage, ...optionsRest },
|
||||||
editingCellFactory,
|
|
||||||
createContext,
|
|
||||||
...cellEditRest
|
...cellEditRest
|
||||||
}
|
}
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@@ -111,7 +134,6 @@ export default (
|
|||||||
...optionsRest,
|
...optionsRest,
|
||||||
...cellEditRest,
|
...cellEditRest,
|
||||||
...this.state,
|
...this.state,
|
||||||
EditingCell,
|
|
||||||
nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [],
|
nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [],
|
||||||
onStart: this.startEditing,
|
onStart: this.startEditing,
|
||||||
onEscape: this.escapeEditing,
|
onEscape: this.escapeEditing,
|
||||||
@@ -120,7 +142,7 @@ export default (
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CellEditContext.Provider
|
<CellEditContext.Provider
|
||||||
value={ { cellEdit: newCellEdit } }
|
value={ { ...newCellEdit } }
|
||||||
>
|
>
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</CellEditContext.Provider>
|
</CellEditContext.Provider>
|
||||||
@@ -128,7 +150,8 @@ export default (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
Provider: CellEditProvider,
|
Provider: CellEditProvider
|
||||||
Consumer: CellEditContext.Consumer
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Consumer = CellEditContext.Consumer;
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
class DateEditor extends Component {
|
class DateEditor extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { defaultValue } = this.props;
|
const { defaultValue, didMount } = this.props;
|
||||||
this.date.valueAsDate = new Date(defaultValue);
|
this.date.valueAsDate = new Date(defaultValue);
|
||||||
this.date.focus();
|
this.date.focus();
|
||||||
|
if (didMount) didMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
@@ -15,7 +16,7 @@ class DateEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { defaultValue, className, ...rest } = this.props;
|
const { defaultValue, didMount, className, ...rest } = this.props;
|
||||||
const editorClass = cs('form-control editor edit-date', className);
|
const editorClass = cs('form-control editor edit-date', className);
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
@@ -33,10 +34,12 @@ DateEditor.propTypes = {
|
|||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.object
|
PropTypes.object
|
||||||
]),
|
]),
|
||||||
defaultValue: PropTypes.string
|
defaultValue: PropTypes.string,
|
||||||
|
didMount: PropTypes.func
|
||||||
};
|
};
|
||||||
DateEditor.defaultProps = {
|
DateEditor.defaultProps = {
|
||||||
className: '',
|
className: '',
|
||||||
defaultValue: ''
|
defaultValue: '',
|
||||||
|
didMount: undefined
|
||||||
};
|
};
|
||||||
export default DateEditor;
|
export default DateEditor;
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
class DropDownEditor extends Component {
|
class DropDownEditor extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { defaultValue } = this.props;
|
const { defaultValue, didMount } = this.props;
|
||||||
this.select.value = defaultValue;
|
this.select.value = defaultValue;
|
||||||
this.select.focus();
|
this.select.focus();
|
||||||
|
if (didMount) didMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
@@ -15,7 +16,7 @@ class DropDownEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { defaultValue, className, options, ...rest } = this.props;
|
const { defaultValue, didMount, className, options, ...rest } = this.props;
|
||||||
const editorClass = cs('form-control editor edit-select', className);
|
const editorClass = cs('form-control editor edit-select', className);
|
||||||
|
|
||||||
const attr = {
|
const attr = {
|
||||||
@@ -51,11 +52,13 @@ DropDownEditor.propTypes = {
|
|||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
value: PropTypes.any
|
value: PropTypes.any
|
||||||
}))
|
}))
|
||||||
]).isRequired
|
]).isRequired,
|
||||||
|
didMount: PropTypes.func
|
||||||
};
|
};
|
||||||
DropDownEditor.defaultProps = {
|
DropDownEditor.defaultProps = {
|
||||||
className: '',
|
className: '',
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
style: {}
|
style: {},
|
||||||
|
didMount: undefined
|
||||||
};
|
};
|
||||||
export default DropDownEditor;
|
export default DropDownEditor;
|
||||||
|
|||||||
44
packages/react-bootstrap-table2-editor/src/editing-cell-consumer.js
vendored
Normal file
44
packages/react-bootstrap-table2-editor/src/editing-cell-consumer.js
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import { Consumer } from './context';
|
||||||
|
import createEditingCell from './editing-cell';
|
||||||
|
|
||||||
|
export default (_, onStartEdit) => {
|
||||||
|
const EditingCell = createEditingCell(_, onStartEdit);
|
||||||
|
const renderWithEditingCell = (props, cellEdit) => {
|
||||||
|
const content = _.get(props.row, props.column.dataField);
|
||||||
|
let editCellstyle = props.column.editCellStyle || {};
|
||||||
|
let editCellclasses = props.column.editCellClasses;
|
||||||
|
if (_.isFunction(props.column.editCellStyle)) {
|
||||||
|
editCellstyle = props.column.editCellStyle(
|
||||||
|
content,
|
||||||
|
props.row,
|
||||||
|
props.rowIndex,
|
||||||
|
props.columnIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (_.isFunction(props.column.editCellClasses)) {
|
||||||
|
editCellclasses = props.column.editCellClasses(
|
||||||
|
content,
|
||||||
|
props.row,
|
||||||
|
props.rowIndex,
|
||||||
|
props.columnIndex)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EditingCell
|
||||||
|
{ ...props }
|
||||||
|
className={ editCellclasses }
|
||||||
|
style={ editCellstyle }
|
||||||
|
{ ...cellEdit }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return props => (
|
||||||
|
<Consumer>
|
||||||
|
{ cellEdit => renderWithEditingCell(props, cellEdit) }
|
||||||
|
</Consumer>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -14,7 +14,7 @@ import TextEditor from './text-editor';
|
|||||||
import EditorIndicator from './editor-indicator';
|
import EditorIndicator from './editor-indicator';
|
||||||
import { TIME_TO_CLOSE_MESSAGE, EDITTYPE } from './const';
|
import { TIME_TO_CLOSE_MESSAGE, EDITTYPE } from './const';
|
||||||
|
|
||||||
export default _ =>
|
export default (_, onStartEdit) =>
|
||||||
class EditingCell extends Component {
|
class EditingCell extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
row: PropTypes.object.isRequired,
|
row: PropTypes.object.isRequired,
|
||||||
@@ -24,6 +24,7 @@ export default _ =>
|
|||||||
onUpdate: PropTypes.func.isRequired,
|
onUpdate: PropTypes.func.isRequired,
|
||||||
onEscape: PropTypes.func.isRequired,
|
onEscape: PropTypes.func.isRequired,
|
||||||
timeToCloseMessage: PropTypes.number,
|
timeToCloseMessage: PropTypes.number,
|
||||||
|
autoSelectText: PropTypes.bool,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
style: PropTypes.object
|
style: PropTypes.object
|
||||||
}
|
}
|
||||||
@@ -31,6 +32,7 @@ export default _ =>
|
|||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
timeToCloseMessage: TIME_TO_CLOSE_MESSAGE,
|
timeToCloseMessage: TIME_TO_CLOSE_MESSAGE,
|
||||||
className: null,
|
className: null,
|
||||||
|
autoSelectText: false,
|
||||||
style: {}
|
style: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +44,8 @@ export default _ =>
|
|||||||
this.handleClick = this.handleClick.bind(this);
|
this.handleClick = this.handleClick.bind(this);
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
this.beforeComplete = this.beforeComplete.bind(this);
|
this.beforeComplete = this.beforeComplete.bind(this);
|
||||||
|
this.asyncbeforeCompete = this.asyncbeforeCompete.bind(this);
|
||||||
|
this.displayErrorMessage = this.displayErrorMessage.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
invalidMessage: null
|
invalidMessage: null
|
||||||
};
|
};
|
||||||
@@ -77,16 +81,41 @@ export default _ =>
|
|||||||
}, timeToCloseMessage);
|
}, timeToCloseMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
displayErrorMessage(message) {
|
||||||
|
this.setState(() => ({
|
||||||
|
invalidMessage: message
|
||||||
|
}));
|
||||||
|
this.createTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncbeforeCompete(newValue) {
|
||||||
|
return (result = { valid: true }) => {
|
||||||
|
const { valid, message } = result;
|
||||||
|
const { onUpdate, row, column } = this.props;
|
||||||
|
if (!valid) {
|
||||||
|
this.displayErrorMessage(message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onUpdate(row, column, newValue);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
beforeComplete(newValue) {
|
beforeComplete(newValue) {
|
||||||
const { onUpdate, row, column } = this.props;
|
const { onUpdate, row, column } = this.props;
|
||||||
if (_.isFunction(column.validator)) {
|
if (_.isFunction(column.validator)) {
|
||||||
const validateForm = column.validator(newValue, row, column);
|
const validateForm = column.validator(
|
||||||
if (_.isObject(validateForm) && !validateForm.valid) {
|
newValue,
|
||||||
this.setState(() => ({
|
row,
|
||||||
invalidMessage: validateForm.message
|
column,
|
||||||
}));
|
this.asyncbeforeCompete(newValue)
|
||||||
this.createTimer();
|
);
|
||||||
return;
|
if (_.isObject(validateForm)) {
|
||||||
|
if (validateForm.async) {
|
||||||
|
return;
|
||||||
|
} else if (!validateForm.valid) {
|
||||||
|
this.displayErrorMessage(validateForm.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onUpdate(row, column, newValue);
|
onUpdate(row, column, newValue);
|
||||||
@@ -121,7 +150,7 @@ export default _ =>
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let editor;
|
let editor;
|
||||||
const { row, column, className, style, rowIndex, columnIndex } = this.props;
|
const { row, column, className, style, rowIndex, columnIndex, autoSelectText } = this.props;
|
||||||
const { dataField } = column;
|
const { dataField } = column;
|
||||||
|
|
||||||
const value = _.get(row, dataField);
|
const value = _.get(row, dataField);
|
||||||
@@ -151,6 +180,10 @@ export default _ =>
|
|||||||
onBlur: this.handleBlur
|
onBlur: this.handleBlur
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (onStartEdit) {
|
||||||
|
editorProps.didMount = () => onStartEdit(row, column, rowIndex, columnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
const isDefaultEditorDefined = _.isObject(column.editor);
|
const isDefaultEditorDefined = _.isObject(column.editor);
|
||||||
|
|
||||||
if (isDefaultEditorDefined) {
|
if (isDefaultEditorDefined) {
|
||||||
@@ -170,13 +203,13 @@ export default _ =>
|
|||||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.SELECT) {
|
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.SELECT) {
|
||||||
editor = <DropdownEditor { ...editorProps } />;
|
editor = <DropdownEditor { ...editorProps } />;
|
||||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.TEXTAREA) {
|
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.TEXTAREA) {
|
||||||
editor = <TextAreaEditor { ...editorProps } />;
|
editor = <TextAreaEditor { ...editorProps } autoSelectText={ autoSelectText } />;
|
||||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.CHECKBOX) {
|
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.CHECKBOX) {
|
||||||
editor = <CheckBoxEditor { ...editorProps } />;
|
editor = <CheckBoxEditor { ...editorProps } />;
|
||||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.DATE) {
|
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.DATE) {
|
||||||
editor = <DateEditor { ...editorProps } />;
|
editor = <DateEditor { ...editorProps } />;
|
||||||
} else {
|
} else {
|
||||||
editor = <TextEditor { ...editorProps } />;
|
editor = <TextEditor { ...editorProps } autoSelectText={ autoSelectText } />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
const EditorIndicator = ({ invalidMessage }) =>
|
const EditorIndicator = ({ invalidMessage }) =>
|
||||||
(
|
(
|
||||||
<div className="alert alert-danger fade in">
|
<div className="alert alert-danger in" role="alert">
|
||||||
<strong>{ invalidMessage }</strong>
|
<strong>{ invalidMessage }</strong>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
43
packages/react-bootstrap-table2-editor/src/row-consumer.js
vendored
Normal file
43
packages/react-bootstrap-table2-editor/src/row-consumer.js
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import { DELAY_FOR_DBCLICK, DBCLICK_TO_CELL_EDIT, CLICK_TO_CELL_EDIT } from './const';
|
||||||
|
import { Consumer } from './context';
|
||||||
|
|
||||||
|
export default (Component, selectRowEnabled) => {
|
||||||
|
const renderWithCellEdit = (props, cellEdit) => {
|
||||||
|
const key = props.value;
|
||||||
|
const editableRow = !(
|
||||||
|
cellEdit.nonEditableRows.length > 0 &&
|
||||||
|
cellEdit.nonEditableRows.indexOf(key) > -1
|
||||||
|
);
|
||||||
|
|
||||||
|
const attrs = {};
|
||||||
|
|
||||||
|
if (selectRowEnabled && cellEdit.mode === DBCLICK_TO_CELL_EDIT) {
|
||||||
|
attrs.DELAY_FOR_DBCLICK = DELAY_FOR_DBCLICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Component
|
||||||
|
{ ...props }
|
||||||
|
{ ...attrs }
|
||||||
|
editingRowIdx={ cellEdit.ridx }
|
||||||
|
editingColIdx={ cellEdit.cidx }
|
||||||
|
editable={ editableRow }
|
||||||
|
onStart={ cellEdit.onStart }
|
||||||
|
clickToEdit={ cellEdit.mode === CLICK_TO_CELL_EDIT }
|
||||||
|
dbclickToEdit={ cellEdit.mode === DBCLICK_TO_CELL_EDIT }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
function withConsumer(props) {
|
||||||
|
return (
|
||||||
|
<Consumer>
|
||||||
|
{ cellEdit => renderWithCellEdit(props, cellEdit) }
|
||||||
|
</Consumer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
withConsumer.displayName = 'WithCellEditingRowConsumer';
|
||||||
|
return withConsumer;
|
||||||
|
};
|
||||||
@@ -5,9 +5,11 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
class TextEditor extends Component {
|
class TextEditor extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { defaultValue } = this.props;
|
const { defaultValue, didMount, autoSelectText } = this.props;
|
||||||
this.text.value = defaultValue;
|
this.text.value = defaultValue;
|
||||||
this.text.focus();
|
this.text.focus();
|
||||||
|
if (autoSelectText) this.text.select();
|
||||||
|
if (didMount) didMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
@@ -15,7 +17,7 @@ class TextEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { defaultValue, className, ...rest } = this.props;
|
const { defaultValue, didMount, className, autoSelectText, ...rest } = this.props;
|
||||||
const editorClass = cs('form-control editor edit-text', className);
|
const editorClass = cs('form-control editor edit-text', className);
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
@@ -36,10 +38,14 @@ TextEditor.propTypes = {
|
|||||||
defaultValue: PropTypes.oneOfType([
|
defaultValue: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.number
|
PropTypes.number
|
||||||
])
|
]),
|
||||||
|
autoSelectText: PropTypes.bool,
|
||||||
|
didMount: PropTypes.func
|
||||||
};
|
};
|
||||||
TextEditor.defaultProps = {
|
TextEditor.defaultProps = {
|
||||||
className: null,
|
className: null,
|
||||||
defaultValue: ''
|
defaultValue: '',
|
||||||
|
autoSelectText: false,
|
||||||
|
didMount: undefined
|
||||||
};
|
};
|
||||||
export default TextEditor;
|
export default TextEditor;
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ class TextAreaEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { defaultValue } = this.props;
|
const { defaultValue, didMount, autoSelectText } = this.props;
|
||||||
this.text.value = defaultValue;
|
this.text.value = defaultValue;
|
||||||
this.text.focus();
|
this.text.focus();
|
||||||
|
if (autoSelectText) this.text.select();
|
||||||
|
if (didMount) didMount();
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
getValue() {
|
||||||
@@ -27,7 +29,7 @@ class TextAreaEditor extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { defaultValue, className, ...rest } = this.props;
|
const { defaultValue, didMount, className, autoSelectText, ...rest } = this.props;
|
||||||
const editorClass = cs('form-control editor edit-textarea', className);
|
const editorClass = cs('form-control editor edit-textarea', className);
|
||||||
return (
|
return (
|
||||||
<textarea
|
<textarea
|
||||||
@@ -50,11 +52,15 @@ TextAreaEditor.propTypes = {
|
|||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.number
|
PropTypes.number
|
||||||
]),
|
]),
|
||||||
onKeyDown: PropTypes.func
|
onKeyDown: PropTypes.func,
|
||||||
|
autoSelectText: PropTypes.bool,
|
||||||
|
didMount: PropTypes.func
|
||||||
};
|
};
|
||||||
TextAreaEditor.defaultProps = {
|
TextAreaEditor.defaultProps = {
|
||||||
className: '',
|
className: '',
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
onKeyDown: undefined
|
autoSelectText: false,
|
||||||
|
onKeyDown: undefined,
|
||||||
|
didMount: undefined
|
||||||
};
|
};
|
||||||
export default TextAreaEditor;
|
export default TextAreaEditor;
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ import React from 'react';
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import _ from 'react-bootstrap-table-next/src/utils';
|
import _ from 'react-bootstrap-table-next/src/utils';
|
||||||
import dataOperator from 'react-bootstrap-table-next/src/store/operators';
|
import dataOperator from 'react-bootstrap-table-next/src/store/operators';
|
||||||
import BootstrapTable from 'react-bootstrap-table-next/src/bootstrap-table';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CLICK_TO_CELL_EDIT,
|
CLICK_TO_CELL_EDIT,
|
||||||
DBCLICK_TO_CELL_EDIT,
|
DBCLICK_TO_CELL_EDIT,
|
||||||
DELAY_FOR_DBCLICK
|
DELAY_FOR_DBCLICK
|
||||||
} from '../src/const';
|
} from '../src/const';
|
||||||
import createCellEditContext from '../src/context';
|
import createCellEditContext, { Consumer } from '../src/context';
|
||||||
import cellEditFactory from '../index';
|
import cellEditFactory from '../index';
|
||||||
|
|
||||||
describe('CellEditContext', () => {
|
describe('CellEditContext', () => {
|
||||||
@@ -42,14 +41,7 @@ describe('CellEditContext', () => {
|
|||||||
|
|
||||||
const defaultSelectRow = undefined;
|
const defaultSelectRow = undefined;
|
||||||
|
|
||||||
const mockBase = jest.fn((props => (
|
const mockBase = jest.fn((() => null));
|
||||||
<BootstrapTable
|
|
||||||
data={ data }
|
|
||||||
columns={ columns }
|
|
||||||
keyField={ keyField }
|
|
||||||
{ ...props }
|
|
||||||
/>
|
|
||||||
)));
|
|
||||||
|
|
||||||
const handleCellChange = jest.fn();
|
const handleCellChange = jest.fn();
|
||||||
|
|
||||||
@@ -75,11 +67,11 @@ describe('CellEditContext', () => {
|
|||||||
selectRow={ selectRow }
|
selectRow={ selectRow }
|
||||||
data={ data }
|
data={ data }
|
||||||
>
|
>
|
||||||
<CellEditContext.Consumer>
|
<Consumer>
|
||||||
{
|
{
|
||||||
cellEditProps => mockBase(cellEditProps)
|
cellEditProps => mockBase(cellEditProps)
|
||||||
}
|
}
|
||||||
</CellEditContext.Consumer>
|
</Consumer>
|
||||||
</CellEditContext.Provider>
|
</CellEditContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -94,10 +86,6 @@ describe('CellEditContext', () => {
|
|||||||
expect(CellEditContext.Provider).toBeDefined();
|
expect(CellEditContext.Provider).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct Consumer property after calling createCellEditContext', () => {
|
|
||||||
expect(CellEditContext.Consumer).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct state.ridx', () => {
|
it('should have correct state.ridx', () => {
|
||||||
expect(wrapper.state().ridx).toBeNull();
|
expect(wrapper.state().ridx).toBeNull();
|
||||||
});
|
});
|
||||||
@@ -113,14 +101,11 @@ describe('CellEditContext', () => {
|
|||||||
it('should pass correct cell editing props to children element', () => {
|
it('should pass correct cell editing props to children element', () => {
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
expect(JSON.stringify(mockBase.mock.calls[0])).toEqual(JSON.stringify([{
|
expect(JSON.stringify(mockBase.mock.calls[0])).toEqual(JSON.stringify([{
|
||||||
cellEdit: {
|
...defaultCellEdit,
|
||||||
...defaultCellEdit,
|
DBCLICK_TO_CELL_EDIT,
|
||||||
CLICK_TO_CELL_EDIT,
|
DELAY_FOR_DBCLICK,
|
||||||
DBCLICK_TO_CELL_EDIT,
|
...wrapper.state(),
|
||||||
DELAY_FOR_DBCLICK,
|
nonEditableRows: []
|
||||||
...wrapper.state(),
|
|
||||||
nonEditableRows: []
|
|
||||||
}
|
|
||||||
}]));
|
}]));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -250,7 +235,8 @@ describe('CellEditContext', () => {
|
|||||||
|
|
||||||
it('should call cellEdit.beforeSaveCell correctly', () => {
|
it('should call cellEdit.beforeSaveCell correctly', () => {
|
||||||
expect(beforeSaveCell).toHaveBeenCalledTimes(1);
|
expect(beforeSaveCell).toHaveBeenCalledTimes(1);
|
||||||
expect(beforeSaveCell).toHaveBeenCalledWith(oldValue, newValue, row, column);
|
expect(beforeSaveCell)
|
||||||
|
.toHaveBeenCalledWith(oldValue, newValue, row, column, expect.anything());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { mount, shallow } from 'enzyme';
|
||||||
|
import _ from 'react-bootstrap-table-next/src/utils';
|
||||||
|
|
||||||
|
import cellEditFactory from '..';
|
||||||
|
import { CLICK_TO_CELL_EDIT } from '../src/const';
|
||||||
|
import createCellEditContext from '../src/context';
|
||||||
|
import bindEditingCell from '../src/editing-cell-consumer';
|
||||||
|
|
||||||
|
describe('Editing Cell Consumer', () => {
|
||||||
|
let wrapper;
|
||||||
|
let cellEdit;
|
||||||
|
const data = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'A'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'B'
|
||||||
|
}];
|
||||||
|
let columns;
|
||||||
|
const rowIndex = 1;
|
||||||
|
const row = { id: 1, name: 'A' };
|
||||||
|
const keyField = 'id';
|
||||||
|
const columnIndex = 1;
|
||||||
|
|
||||||
|
const { Provider } = createCellEditContext(_);
|
||||||
|
const WithCellEditComponent = bindEditingCell(_);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Name'
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if column.editCellClasses is defined as string', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||||
|
columns[1].editCellClasses = 'test-class-1';
|
||||||
|
wrapper = shallow(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent
|
||||||
|
row={ row }
|
||||||
|
column={ columns[1] }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
columnIndex={ columnIndex }
|
||||||
|
/>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
wrapper = wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject className target component correctly', () => {
|
||||||
|
expect(wrapper.hasClass(`${columns[1].editCellClasses}`)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if column.editCellStyle is defined as object', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||||
|
columns[1].editCellStyle = { color: 'pink' };
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent
|
||||||
|
row={ row }
|
||||||
|
column={ columns[1] }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
columnIndex={ columnIndex }
|
||||||
|
/>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject style target component correctly', () => {
|
||||||
|
expect(wrapper.find('.react-bootstrap-table-editing-cell').prop('style')).toEqual(columns[1].editCellStyle);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if column.editCellClasses is defined as function', () => {
|
||||||
|
const className = 'test-class-1';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||||
|
columns[1].editCellClasses = jest.fn().mockReturnValue(className);
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent
|
||||||
|
row={ row }
|
||||||
|
column={ columns[1] }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
columnIndex={ columnIndex }
|
||||||
|
/>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject empty className and style to target component', () => {
|
||||||
|
expect(wrapper.find(className)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call column.editCellClasses function correctly', () => {
|
||||||
|
expect(columns[1].editCellClasses).toHaveBeenCalledTimes(1);
|
||||||
|
expect(columns[1].editCellClasses).toHaveBeenCalledWith(
|
||||||
|
_.get(row, columns[1].dataField),
|
||||||
|
row,
|
||||||
|
rowIndex,
|
||||||
|
columnIndex
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if column.editCellStyle is defined as function', () => {
|
||||||
|
const style = { color: 'blue' };
|
||||||
|
beforeEach(() => {
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||||
|
columns[1].editCellStyle = jest.fn().mockReturnValue(style);
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent
|
||||||
|
row={ row }
|
||||||
|
column={ columns[1] }
|
||||||
|
rowIndex={ rowIndex }
|
||||||
|
columnIndex={ columnIndex }
|
||||||
|
/>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject style target component correctly', () => {
|
||||||
|
expect(wrapper.find('.react-bootstrap-table-editing-cell').prop('style')).toEqual(style);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call column.editCellStyle function correctly', () => {
|
||||||
|
expect(columns[1].editCellStyle).toHaveBeenCalledTimes(1);
|
||||||
|
expect(columns[1].editCellStyle).toHaveBeenCalledWith(
|
||||||
|
_.get(row, columns[1].dataField),
|
||||||
|
row,
|
||||||
|
rowIndex,
|
||||||
|
columnIndex
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
138
packages/react-bootstrap-table2-editor/test/row-consumer.test.js
Normal file
138
packages/react-bootstrap-table2-editor/test/row-consumer.test.js
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { mount } from 'enzyme';
|
||||||
|
import _ from 'react-bootstrap-table-next/src/utils';
|
||||||
|
import op from 'react-bootstrap-table-next/src/store/operators';
|
||||||
|
|
||||||
|
import cellEditFactory from '..';
|
||||||
|
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT, DELAY_FOR_DBCLICK } from '../src/const';
|
||||||
|
import createCellEditContext from '../src/context';
|
||||||
|
import withRowLevelCellEdit from '../src/row-consumer';
|
||||||
|
|
||||||
|
describe('Row Consumer', () => {
|
||||||
|
let wrapper;
|
||||||
|
let cellEdit;
|
||||||
|
const data = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'A'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'B'
|
||||||
|
}];
|
||||||
|
const row = { id: 1, name: 'A' };
|
||||||
|
const keyField = 'id';
|
||||||
|
const value = _.get(row, keyField);
|
||||||
|
|
||||||
|
const { Provider } = createCellEditContext(_, op, false, jest.fn());
|
||||||
|
const BaseComponent = () => null;
|
||||||
|
|
||||||
|
describe('if cellEdit.nonEditableRows is undefined', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const WithCellEditComponent = withRowLevelCellEdit(
|
||||||
|
props => <BaseComponent { ...props } />,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent value={ value } />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject correct props to target component', () => {
|
||||||
|
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editingRowIdx')).toBeNull();
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editingColIdx')).toBeNull();
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editable')).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if cellEdit.nonEditableRows is defined', () => {
|
||||||
|
const nonEditableRows = jest.fn().mockReturnValue([value]);
|
||||||
|
describe('if value prop is match in one of cellEdit.nonEditableRows', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const WithCellEditComponent = withRowLevelCellEdit(
|
||||||
|
props => <BaseComponent { ...props } />,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT, nonEditableRows });
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent value={ value } />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject correct editable prop as false to target component', () => {
|
||||||
|
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editable')).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if value prop is not match in one of cellEdit.nonEditableRows', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const WithCellEditComponent = withRowLevelCellEdit(
|
||||||
|
props => <BaseComponent { ...props } />,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT, nonEditableRows });
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent value={ 2 } />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject correct editable prop as false to target component', () => {
|
||||||
|
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editable')).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(`if selectRowEnabled argument is true and cellEdit.mode is ${DBCLICK_TO_CELL_EDIT}`, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const WithCellEditComponent = withRowLevelCellEdit(
|
||||||
|
props => <BaseComponent { ...props } />,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
cellEdit = cellEditFactory({ mode: DBCLICK_TO_CELL_EDIT });
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent value={ value } />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject correct DELAY_FOR_DBCLICK prop to target component', () => {
|
||||||
|
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(BaseComponent).prop('DELAY_FOR_DBCLICK')).toEqual(DELAY_FOR_DBCLICK);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if cellEdit.ridx and cellEdit.cidx are defined', () => {
|
||||||
|
const ridx = 0;
|
||||||
|
const cidx = 1;
|
||||||
|
beforeEach(() => {
|
||||||
|
const WithCellEditComponent = withRowLevelCellEdit(
|
||||||
|
props => <BaseComponent { ...props } />,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||||
|
<WithCellEditComponent value={ value } />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
wrapper.instance().startEditing(ridx, cidx);
|
||||||
|
wrapper.update();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should inject correct editable prop as false to target component', () => {
|
||||||
|
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editingRowIdx')).toEqual(ridx);
|
||||||
|
expect(wrapper.find(BaseComponent).prop('editingColIdx')).toEqual(cidx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
182
packages/react-bootstrap-table2-example/examples/basic/exposed-function.js
vendored
Normal file
182
packages/react-bootstrap-table2-example/examples/basic/exposed-function.js
vendored
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/* eslint no-return-assign: 0 */
|
||||||
|
/* eslint no-console: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||||
|
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(63);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
sort: true
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
sort: true,
|
||||||
|
filter: textFilter()
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
sort: true,
|
||||||
|
filter: textFilter()
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
class ExposedFunctionTable extends React.Component {
|
||||||
|
handleGetCurrentData = () => {
|
||||||
|
console.log(this.node.table.props.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetSelectedData = () => {
|
||||||
|
console.log(this.node.selectionContext.state.selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetExpandedData = () => {
|
||||||
|
console.log(this.node.rowExpandContext.state.expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentPage = () => {
|
||||||
|
console.log(this.node.paginationContext.currPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentSizePerPage = () => {
|
||||||
|
console.log(this.node.paginationContext.currSizePerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentSortColumn = () => {
|
||||||
|
console.log(this.node.sortContext.state.sortColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentSortOrder = () => {
|
||||||
|
console.log(this.node.sortContext.state.sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentFilter = () => {
|
||||||
|
console.log(this.node.filterContext.currFilters);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>.....</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
showExpandColumn: true
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentData }>Get Current Display Rows</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetSelectedData }>Get Current Selected Rows</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetExpandedData }>Get Current Expanded Rows</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentPage }>Get Current Page</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentSizePerPage }>Get Current Size Per Page</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentSortColumn }>Get Current Sort Column</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentSortOrder }>Get Current Sort Order</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentFilter }>Get Current Filter Information</button>
|
||||||
|
<BootstrapTable
|
||||||
|
ref={ n => this.node = n }
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class ExposedFunctionTable extends React.Component {
|
||||||
|
handleGetCurrentData = () => {
|
||||||
|
console.log(this.node.table.props.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetSelectedData = () => {
|
||||||
|
console.log(this.node.selectionContext.state.selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetExpandedData = () => {
|
||||||
|
console.log(this.node.rowExpandContext.state.expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentPage = () => {
|
||||||
|
console.log(this.node.paginationContext.currPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentSizePerPage = () => {
|
||||||
|
console.log(this.node.paginationContext.currSizePerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentSortColumn = () => {
|
||||||
|
console.log(this.node.sortContext.state.sortColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentSortOrder = () => {
|
||||||
|
console.log(this.node.sortContext.state.sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleGetCurrentFilter = () => {
|
||||||
|
console.log(this.node.filterContext.currFilters);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
showExpandColumn: true
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentData }>Get Current Display Rows</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetSelectedData }>Get Current Selected Rows</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetExpandedData }>Get Current Expanded Rows</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentPage }>Get Current Page</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentSizePerPage }>Get Current Size Per Page</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentSortColumn }>Get Current Sort Column</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentSortOrder }>Get Current Sort Order</button>
|
||||||
|
<button className="btn btn-default" onClick={ this.handleGetCurrentFilter }>Get Current Filter Information</button>
|
||||||
|
<BootstrapTable
|
||||||
|
ref={ n => this.node = n }
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
|
||||||
import { productsGenerator } from 'utils/common';
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
const products = productsGenerator(5000);
|
const products = productsGenerator(3000);
|
||||||
|
|
||||||
const columns = [{
|
const columns = [{
|
||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
@@ -17,16 +16,25 @@ const columns = [{
|
|||||||
text: 'Product Price'
|
text: 'Product Price'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
showExpandColumn: true,
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ products }
|
data={ products }
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
selectRow={ { mode: 'checkbox' } }
|
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||||
cellEdit={ cellEditFactory({
|
expandRow={ expandRow }
|
||||||
mode: 'click'
|
|
||||||
}) }
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
54
packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js
vendored
Normal file
54
packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
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'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField='id'
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ { mode: 'checkbox' } }
|
||||||
|
tabIndexCell
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ { mode: 'checkbox' } }
|
||||||
|
tabIndexCell
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
78
packages/react-bootstrap-table2-example/examples/cell-edit/auto-select-text-input-table.js
vendored
Normal file
78
packages/react-bootstrap-table2-example/examples/cell-edit/auto-select-text-input-table.js
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { jobsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const jobs = jobsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Job ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Job Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'owner',
|
||||||
|
text: 'Job Owner'
|
||||||
|
}, {
|
||||||
|
dataField: 'type',
|
||||||
|
text: 'Job Type',
|
||||||
|
editor: {
|
||||||
|
type: Type.TEXTAREA
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Job ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Job Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'owner',
|
||||||
|
text: 'Job Owner'
|
||||||
|
}, {
|
||||||
|
dataField: 'type',
|
||||||
|
text: 'Job Type',
|
||||||
|
editor: {
|
||||||
|
type: Type.TEXTAREA
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ jobs }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={
|
||||||
|
cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
autoSelectText: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Auto Select Text Input Field When Editing</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ jobs }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={
|
||||||
|
cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
autoSelectText: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
86
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-hooks-table.js
vendored
Normal file
86
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-hooks-table.js
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-console: 0 */
|
||||||
|
/* eslint no-alert: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
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 cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
function beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Do you want to accep this change?')) {
|
||||||
|
done(true);
|
||||||
|
} else {
|
||||||
|
done(false);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
beforeSaveCell
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
function beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Do you want to accep this change?')) {
|
||||||
|
done(true);
|
||||||
|
} else {
|
||||||
|
done(false);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h2>You will get a confirm prompt when you try to save a cell</h2>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
beforeSaveCell
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
101
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-validator-table.js
vendored
Normal file
101
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-validator-table.js
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
validator: (newValue, row, column, done) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (isNaN(newValue)) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should be numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (newValue < 2000) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should bigger than 2000'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done();
|
||||||
|
}, 2000);
|
||||||
|
return {
|
||||||
|
async: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
validator: (newValue, row, column, done) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (isNaN(newValue)) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should be numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (newValue < 2000) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should bigger than 2000'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done();
|
||||||
|
}, 2000);
|
||||||
|
return {
|
||||||
|
async: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
blurToSave: true
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Product Price should bigger than $2000</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
blurToSave: true
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -41,6 +41,7 @@ const columns = [{
|
|||||||
columns={ columns }
|
columns={ columns }
|
||||||
cellEdit={ cellEditFactory({
|
cellEdit={ cellEditFactory({
|
||||||
mode: 'click',
|
mode: 'click',
|
||||||
|
onStartEdit: (row, column, rowIndex, columnIndex) => { console.log('start to edit!!!'); },
|
||||||
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
|
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
|
||||||
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
|
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
|
||||||
}) }
|
}) }
|
||||||
@@ -55,6 +56,7 @@ export default () => (
|
|||||||
columns={ columns }
|
columns={ columns }
|
||||||
cellEdit={ cellEditFactory({
|
cellEdit={ cellEditFactory({
|
||||||
mode: 'click',
|
mode: 'click',
|
||||||
|
onStartEdit: (row, column, rowIndex, columnIndex) => { console.log('Start to edit!!!'); },
|
||||||
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
|
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
|
||||||
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
|
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
|
||||||
}) }
|
}) }
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const columns = [{
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Dropdown Editor</h3>
|
<h3>Checkbox Editor</h3>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ todos }
|
data={ todos }
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ const columns = [{
|
|||||||
}, {
|
}, {
|
||||||
dataField: 'quality',
|
dataField: 'quality',
|
||||||
text: 'Product Quality',
|
text: 'Product Quality',
|
||||||
editorRenderer: (editorProps, value, row, rowIndex, columnIndex) => (
|
editorRenderer: (editorProps, value, row, column, rowIndex, columnIndex) => (
|
||||||
<QualityRanger { ...editorProps } value={ value } />
|
<QualityRanger { ...editorProps } value={ value } />
|
||||||
)
|
)
|
||||||
}];
|
}];
|
||||||
@@ -118,7 +118,7 @@ const columns = [{
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Dropdown Editor</h3>
|
<h3>Custom Editor</h3>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ products }
|
data={ products }
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const columns = [{
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Dropdown Editor</h3>
|
<h3>Date Editor</h3>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ stocks }
|
data={ stocks }
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
clickToEdit: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
clickToEdit: true
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
cellEdit={ cellEditFactory({ mode: 'dbclick' }) }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Double click to edit cell</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
cellEdit={ cellEditFactory({ mode: 'dbclick' }) }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -56,7 +56,7 @@ const columns = [{
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Dropdown Editor</h3>
|
<h3>Textarea Editor</h3>
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
keyField="id"
|
keyField="id"
|
||||||
data={ jobs }
|
data={ jobs }
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/* eslint max-len: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsQualityGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsQualityGenerator(6);
|
||||||
|
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: 0, label: 'good' },
|
||||||
|
{ value: 1, label: 'Bad' },
|
||||||
|
{ value: 2, label: 'unknown' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: 0, label: 'good' },
|
||||||
|
{ value: 1, label: 'Bad' },
|
||||||
|
{ value: 2, label: 'unknown' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3><code>selectFilter.options</code> accept an Array and we keep that order when rendering the options</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/* eslint no-unused-vars: 0 */
|
/* eslint no-unused-vars: 0 */
|
||||||
/* eslint no-alert: 0 */
|
/* eslint no-alert: 0 */
|
||||||
|
/* eslint no-console: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
@@ -12,7 +13,22 @@ const columns = [{
|
|||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
text: 'Product ID',
|
text: 'Product ID',
|
||||||
events: {
|
events: {
|
||||||
onClick: () => alert('Click on Product ID field')
|
onClick: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
alert('Click on Product ID field');
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
console.log('onMouseEnter on Product ID field');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
dataField: 'name',
|
dataField: 'name',
|
||||||
@@ -29,7 +45,22 @@ const columns = [{
|
|||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
text: 'Product ID',
|
text: 'Product ID',
|
||||||
events: {
|
events: {
|
||||||
onClick: () => alert('Click on Product ID field')
|
onClick: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
alert('Click on Product ID field');
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
console.log('onMouseEnter on Product ID field');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
dataField: 'name',
|
dataField: 'name',
|
||||||
@@ -44,7 +75,7 @@ const columns = [{
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Try to Click on Product ID columns</h3>
|
<h3>Try to Click or Mouse over on Product ID columns</h3>
|
||||||
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
<Code>{ sourceCode }</Code>
|
<Code>{ sourceCode }</Code>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React from 'react';
|
|||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
import Code from 'components/common/code-block';
|
import Code from 'components/common/code-block';
|
||||||
import { productsGenerator } from 'utils/common';
|
import { productsGenerator, withOnSale } from 'utils/common';
|
||||||
|
|
||||||
const products = productsGenerator();
|
const products = withOnSale(productsGenerator());
|
||||||
|
|
||||||
function priceFormatter(cell, row) {
|
function priceFormatter(cell, row) {
|
||||||
if (row.onSale) {
|
if (row.onSale) {
|
||||||
|
|||||||
221
packages/react-bootstrap-table2-example/examples/columns/dummy-column-table.js
vendored
Normal file
221
packages/react-bootstrap-table2-example/examples/columns/dummy-column-table.js
vendored
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
/* eslint jsx-a11y/label-has-for: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
|
||||||
|
|
||||||
|
const products = [
|
||||||
|
{ id: 12, name: 'Item 12', price: 12.5, inStock: false },
|
||||||
|
{ id: 13, name: 'Item 13', price: 13.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 = `\
|
||||||
|
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 {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { products };
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleInStock = () => {
|
||||||
|
let newProducts = [...this.state.products];
|
||||||
|
newProducts = newProducts.map((d) => {
|
||||||
|
if (d.id === 13) {
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
inStock: !d.inStock
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
this.setState(curr => ({ ...curr, products: newProducts }));
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="h2">Products</h1>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ this.state.products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
||||||
|
Toggle item 13 stock status
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
class ProductList extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { products };
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleInStock = () => {
|
||||||
|
let newProducts = [...this.state.products];
|
||||||
|
newProducts = newProducts.map((d) => {
|
||||||
|
if (d.id === 13) {
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
inStock: !d.inStock
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
this.setState(curr => ({ ...curr, products: newProducts }));
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>Action 1 and Action 2 are dummy column</h3>
|
||||||
|
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
||||||
|
Toggle item 13 stock status
|
||||||
|
</button>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ this.state.products }
|
||||||
|
columns={ columns }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductList;
|
||||||
98
packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js
vendored
Normal file
98
packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/* 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 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 from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const MyExportCSV = (props) => {
|
||||||
|
const handleClick = () => {
|
||||||
|
props.onExport();
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-success" onClick={ handleClick }>Export to CSV</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable { ...props.baseProps } />
|
||||||
|
<hr />
|
||||||
|
<MyExportCSV { ...props.csvProps } />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const MyExportCSV = (props) => {
|
||||||
|
const handleClick = () => {
|
||||||
|
// passing my custom data
|
||||||
|
props.onExport(products.filter(r => r.id > 2));
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button className="btn btn-success" onClick={ handleClick }>Only export Product ID bigger than 2</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable { ...props.baseProps } />
|
||||||
|
<hr />
|
||||||
|
<MyExportCSV { ...props.csvProps } />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
140
packages/react-bootstrap-table2-example/examples/csv/export-only-selected.js
vendored
Normal file
140
packages/react-bootstrap-table2-example/examples/csv/export-only-selected.js
vendored
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import ToolkitProvider, { CSVExport } from 'react-bootstrap-table2-toolkit';
|
||||||
|
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const { ExportCSVButton } = CSVExport;
|
||||||
|
const products1 = productsGenerator(15);
|
||||||
|
const products2 = productsGenerator(15);
|
||||||
|
|
||||||
|
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, { CSVExport } from 'react-bootstrap-table2-toolkit';
|
||||||
|
|
||||||
|
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={ products1 }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV={ { onlyExportSelection: true, exportAll: true } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products2 }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV={ { onlyExportSelection: true, exportAll: false } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Export all selected row</h3>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products1 }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV={ { onlyExportSelection: true, exportAll: true } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<h3>Export all selected rows in currect visible rows</h3>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products2 }
|
||||||
|
columns={ columns }
|
||||||
|
exportCSV={ { onlyExportSelection: true, exportAll: false } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
pagination={ paginationFactory() }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
106
packages/react-bootstrap-table2-example/examples/pagination/custom-page-button.js
vendored
Normal file
106
packages/react-bootstrap-table2-example/examples/pagination/custom-page-button.js
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint jsx-a11y/href-no-hash: 0 */
|
||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
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';
|
||||||
|
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 from 'react-bootstrap-table2-paginator';
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const pageButtonRenderer = ({
|
||||||
|
page,
|
||||||
|
active,
|
||||||
|
disable,
|
||||||
|
title,
|
||||||
|
onPageChange
|
||||||
|
}) => {
|
||||||
|
const handleClick = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onPageChange(page);
|
||||||
|
};
|
||||||
|
const activeStyle = {};
|
||||||
|
if (active) {
|
||||||
|
activeStyle.backgroundColor = 'black';
|
||||||
|
activeStyle.color = 'white';
|
||||||
|
} else {
|
||||||
|
activeStyle.backgroundColor = 'gray';
|
||||||
|
activeStyle.color = 'black';
|
||||||
|
}
|
||||||
|
if (typeof page === 'string') {
|
||||||
|
activeStyle.backgroundColor = 'white';
|
||||||
|
activeStyle.color = 'black';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li className="page-item">
|
||||||
|
<a href="#" onClick={ handleClick } style={ activeStyle }>{ page }</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
pageButtonRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
const pageButtonRenderer = ({
|
||||||
|
page,
|
||||||
|
active,
|
||||||
|
disable,
|
||||||
|
title,
|
||||||
|
onPageChange
|
||||||
|
}) => {
|
||||||
|
const handleClick = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onPageChange(page);
|
||||||
|
};
|
||||||
|
const activeStyle = {};
|
||||||
|
if (active) {
|
||||||
|
activeStyle.backgroundColor = 'black';
|
||||||
|
activeStyle.color = 'white';
|
||||||
|
} else {
|
||||||
|
activeStyle.backgroundColor = 'gray';
|
||||||
|
activeStyle.color = 'black';
|
||||||
|
}
|
||||||
|
if (typeof page === 'string') {
|
||||||
|
activeStyle.backgroundColor = 'white';
|
||||||
|
activeStyle.color = 'black';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li className="page-item">
|
||||||
|
<a href="#" onClick={ handleClick } style={ activeStyle }>{ page }</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
pageButtonRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
78
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list.js
vendored
Normal file
78
packages/react-bootstrap-table2-example/examples/pagination/custom-page-list.js
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint jsx-a11y/href-no-hash: 0 */
|
||||||
|
/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
|
||||||
|
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';
|
||||||
|
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 from 'react-bootstrap-table2-paginator';
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const pageListRenderer = ({
|
||||||
|
pages,
|
||||||
|
onPageChange
|
||||||
|
}) => {
|
||||||
|
const pageWithoutIndication = pages.filter(p => typeof p.page !== 'string');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
pageWithoutIndication.map(p => (
|
||||||
|
<button className="btn btn-success" onClick={ () => onPageChange(p.page) }>{ p.page }</button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
pageListRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
const pageListRenderer = ({
|
||||||
|
pages,
|
||||||
|
onPageChange
|
||||||
|
}) => {
|
||||||
|
const pageWithoutIndication = pages.filter(p => typeof p.page !== 'string');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
pageWithoutIndication.map(p => (
|
||||||
|
<button className="btn btn-success" onClick={ () => onPageChange(p.page) }>{ p.page }</button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
pageListRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
96
packages/react-bootstrap-table2-example/examples/pagination/custom-size-per-page-option.js
vendored
Normal file
96
packages/react-bootstrap-table2-example/examples/pagination/custom-size-per-page-option.js
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint jsx-a11y/href-no-hash: 0 */
|
||||||
|
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';
|
||||||
|
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 from 'react-bootstrap-table2-paginator';
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const sizePerPageOptionRenderer = ({
|
||||||
|
text,
|
||||||
|
page,
|
||||||
|
onSizePerPageChange
|
||||||
|
}) => (
|
||||||
|
<li
|
||||||
|
key={ text }
|
||||||
|
role="presentation"
|
||||||
|
className="dropdown-item"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
tabIndex="-1"
|
||||||
|
role="menuitem"
|
||||||
|
data-page={ page }
|
||||||
|
onMouseDown={ (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onSizePerPageChange(page);
|
||||||
|
} }
|
||||||
|
style={ { color: 'red' } }
|
||||||
|
>
|
||||||
|
{ text }
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
sizePerPageOptionRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
const sizePerPageOptionRenderer = ({
|
||||||
|
text,
|
||||||
|
page,
|
||||||
|
onSizePerPageChange
|
||||||
|
}) => (
|
||||||
|
<li
|
||||||
|
key={ text }
|
||||||
|
role="presentation"
|
||||||
|
className="dropdown-item"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
tabIndex="-1"
|
||||||
|
role="menuitem"
|
||||||
|
data-page={ page }
|
||||||
|
onMouseDown={ (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onSizePerPageChange(page);
|
||||||
|
} }
|
||||||
|
style={ { color: 'red' } }
|
||||||
|
>
|
||||||
|
{ text }
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
sizePerPageOptionRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
89
packages/react-bootstrap-table2-example/examples/pagination/custom-size-per-page.js
vendored
Normal file
89
packages/react-bootstrap-table2-example/examples/pagination/custom-size-per-page.js
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint jsx-a11y/href-no-hash: 0 */
|
||||||
|
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';
|
||||||
|
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 from 'react-bootstrap-table2-paginator';
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const sizePerPageRenderer = ({
|
||||||
|
options,
|
||||||
|
currSizePerPage,
|
||||||
|
onSizePerPageChange
|
||||||
|
}) => (
|
||||||
|
<div className="btn-group" role="group">
|
||||||
|
{
|
||||||
|
options.map((option) => {
|
||||||
|
const isSelect = currSizePerPage === \`$\{option.page}\`;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={ option.text }
|
||||||
|
type="button"
|
||||||
|
onClick={ () => onSizePerPageChange(option.page) }
|
||||||
|
className={ \`btn $\{isSelect ? 'btn-secondary' : 'btn-warning'}\` }
|
||||||
|
>
|
||||||
|
{ option.text }
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
sizePerPageRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />s
|
||||||
|
`;
|
||||||
|
|
||||||
|
const sizePerPageRenderer = ({
|
||||||
|
options,
|
||||||
|
currSizePerPage,
|
||||||
|
onSizePerPageChange
|
||||||
|
}) => (
|
||||||
|
<div className="btn-group" role="group">
|
||||||
|
{
|
||||||
|
options.map(option => (
|
||||||
|
<button
|
||||||
|
key={ option.text }
|
||||||
|
type="button"
|
||||||
|
onClick={ () => onSizePerPageChange(option.page) }
|
||||||
|
className={ `btn ${currSizePerPage === `${option.page}` ? 'btn-secondary' : 'btn-warning'}` }
|
||||||
|
>
|
||||||
|
{ option.text }
|
||||||
|
</button>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
sizePerPageRenderer
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
166
packages/react-bootstrap-table2-example/examples/pagination/fully-custom-pagination.js
vendored
Normal file
166
packages/react-bootstrap-table2-example/examples/pagination/fully-custom-pagination.js
vendored
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider } 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 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
|
||||||
|
};
|
||||||
|
|
||||||
|
class FullyCustomPagination extends React.Component {
|
||||||
|
handleNextPage = ({
|
||||||
|
page,
|
||||||
|
onPageChange
|
||||||
|
}) => () => {
|
||||||
|
onPageChange(page + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePrevPage = ({
|
||||||
|
page,
|
||||||
|
onPageChange
|
||||||
|
}) => () => {
|
||||||
|
onPageChange(page - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSizePerPage = ({
|
||||||
|
page,
|
||||||
|
onSizePerPageChange
|
||||||
|
}, newSizePerPage) => {
|
||||||
|
onSizePerPageChange(newSizePerPage, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p>Current Page: { paginationProps.page }</p>
|
||||||
|
<p>Current SizePerPage: { paginationProps.sizePerPage }</p>
|
||||||
|
</div>
|
||||||
|
<div className="btn-group" role="group">
|
||||||
|
<button className="btn btn-primary" onClick={ this.handleNextPage(paginationProps) }>Next Page</button>
|
||||||
|
<button className="btn btn-success" onClick={ this.handlePrevPage(paginationProps) }>Prev Page</button>
|
||||||
|
<button className="btn btn-danger" onClick={ () => this.handleSizePerPage(paginationProps, 10) }>Size Per Page: 10</button>
|
||||||
|
<button className="btn btn-warning" onClick={ () => this.handleSizePerPage(paginationProps, 25) }>Size Per Page: 25</button>
|
||||||
|
</div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class FullyCustomPagination extends React.Component {
|
||||||
|
handleNextPage = ({
|
||||||
|
page,
|
||||||
|
onPageChange
|
||||||
|
}) => () => {
|
||||||
|
onPageChange(page + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePrevPage = ({
|
||||||
|
page,
|
||||||
|
onPageChange
|
||||||
|
}) => () => {
|
||||||
|
onPageChange(page - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSizePerPage = ({
|
||||||
|
page,
|
||||||
|
onSizePerPageChange
|
||||||
|
}, newSizePerPage) => {
|
||||||
|
onSizePerPageChange(newSizePerPage, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<p>Current Page: { paginationProps.page }</p>
|
||||||
|
<p>Current SizePerPage: { paginationProps.sizePerPage }</p>
|
||||||
|
</div>
|
||||||
|
<div className="btn-group" role="group">
|
||||||
|
<button className="btn btn-primary" onClick={ this.handleNextPage(paginationProps) }>Next Page</button>
|
||||||
|
<button className="btn btn-success" onClick={ this.handlePrevPage(paginationProps) }>Prev Page</button>
|
||||||
|
<button className="btn btn-danger" onClick={ () => this.handleSizePerPage(paginationProps, 10) }>Size Per Page: 10</button>
|
||||||
|
<button className="btn btn-warning" onClick={ () => this.handleSizePerPage(paginationProps, 25) }>Size Per Page: 25</button>
|
||||||
|
</div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
102
packages/react-bootstrap-table2-example/examples/pagination/standalone-pagination-list.js
vendored
Normal file
102
packages/react-bootstrap-table2-example/examples/pagination/standalone-pagination-list.js
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/* 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 Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator(87);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
|
const 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>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
// const pagination = paginationFactory(options);
|
||||||
|
|
||||||
|
export default class StandalonePaginationList extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
102
packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js
vendored
Normal file
102
packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/* eslint react/prefer-stateless-function: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import paginationFactory, { PaginationProvider, SizePerPageDropdownStandalone } 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, SizePerPageDropdownStandalone } 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>
|
||||||
|
<SizePerPageDropdownStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
custom: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
// const pagination = paginationFactory(options);
|
||||||
|
|
||||||
|
export default class StandaloneSizePerPage extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<SizePerPageDropdownStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
/* eslint react/prop-types: 0 */
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
@@ -33,7 +34,7 @@ const expandRow = {
|
|||||||
}
|
}
|
||||||
return <b>+</b>;
|
return <b>+</b>;
|
||||||
},
|
},
|
||||||
expandColumnRenderer: ({ expanded }) => {
|
expandColumnRenderer: ({ expanded, rowKey, expandable }) => {
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
return (
|
return (
|
||||||
<b>-</b>
|
<b>-</b>
|
||||||
|
|||||||
77
packages/react-bootstrap-table2-example/examples/row-expand/expand-by-column-only.js
vendored
Normal file
77
packages/react-bootstrap-table2-example/examples/row-expand/expand-by-column-only.js
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsExpandRowsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsExpandRowsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandByColumnOnly: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
showExpandColumn: true,
|
||||||
|
expandByColumnOnly: true
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField='id'
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Only able to expand row via clicking expand column(indicator)</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
73
packages/react-bootstrap-table2-example/examples/row-expand/expand-only-one.js
vendored
Normal file
73
packages/react-bootstrap-table2-example/examples/row-expand/expand-only-one.js
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsExpandRowsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsExpandRowsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
onlyOneExpanding: true,
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField='id'
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -25,6 +25,7 @@ const expandRow = {
|
|||||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
showExpandColumn: true,
|
||||||
nonExpandable: [1, 3]
|
nonExpandable: [1, 3]
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ const expandRow = {
|
|||||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
showExpandColumn: true,
|
||||||
nonExpandable: [1, 3]
|
nonExpandable: [1, 3]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
59
packages/react-bootstrap-table2-example/examples/row-selection/hide-select-all.js
vendored
Normal file
59
packages/react-bootstrap-table2-example/examples/row-selection/hide-select-all.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
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'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
hideSelectAll: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
hideSelectAll: true
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField='id'
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js
vendored
Normal file
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* eslint no-alert: 0 */
|
||||||
|
/* eslint consistent-return: 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'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
class AdvSelectionManagment extends React.Component {
|
||||||
|
handleOnSelect = (row, isSelect) => {
|
||||||
|
if (isSelect && row.id < 3) {
|
||||||
|
alert('Oops, You can not select Product ID which less than 3');
|
||||||
|
return false; // return false to deny current select action
|
||||||
|
}
|
||||||
|
return true; // return true or dont return to approve current select action
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnSelectAll = (isSelect, rows) => {
|
||||||
|
if (isSelect) {
|
||||||
|
return rows.filter(r => r.id >= 3).map(r => r.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
onSelect: this.handleOnSelect,
|
||||||
|
onSelectAll: this.handleOnSelectAll
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>You can not select Product ID less than 3</h3>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class AdvSelectionManagment extends React.Component {
|
||||||
|
handleOnSelect = (row, isSelect) => {
|
||||||
|
if (isSelect && row.id < 3) {
|
||||||
|
alert('Oops, You can not select Product ID which less than 3');
|
||||||
|
return false; // return false to deny current select action
|
||||||
|
}
|
||||||
|
return true; // return true or dont return to approve current select action
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnSelectAll = (isSelect, rows) => {
|
||||||
|
if (isSelect) {
|
||||||
|
return rows.filter(r => r.id >= 3).map(r => r.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
onSelect: this.handleOnSelect,
|
||||||
|
onSelectAll: this.handleOnSelectAll
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>You can not select Product ID less than 3</h3>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-with-expansion.js
vendored
Normal file
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-with-expansion.js
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
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'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
clickToExpand: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
showExpandColumn: true,
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
clickToExpand: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const expandRow = {
|
||||||
|
showExpandColumn: true,
|
||||||
|
renderer: row => (
|
||||||
|
<div>
|
||||||
|
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||||
|
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||||
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField='id'
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
selectRow={ selectRow }
|
||||||
|
expandRow={ expandRow }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint no-unused-vars: 0 */
|
/* eslint no-unused-vars: 0 */
|
||||||
/* eslint no-alert: 0 */
|
/* eslint no-console: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
@@ -21,7 +21,10 @@ const columns = [{
|
|||||||
|
|
||||||
const rowEvents = {
|
const rowEvents = {
|
||||||
onClick: (e, row, rowIndex) => {
|
onClick: (e, row, rowIndex) => {
|
||||||
alert(`clicked on row with index: ${rowIndex}`);
|
console.log(`clicked on row with index: ${rowIndex}`);
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, row, rowIndex) => {
|
||||||
|
console.log(`enter on row with index: ${rowIndex}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,7 +44,10 @@ const columns = [{
|
|||||||
|
|
||||||
const rowEvents = {
|
const rowEvents = {
|
||||||
onClick: (e, row, rowIndex) => {
|
onClick: (e, row, rowIndex) => {
|
||||||
alert(\`clicked on row with index: \${rowIndex}\`);
|
console.log(\`clicked on row with index: \${rowIndex}\`);
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, row, rowIndex) => {
|
||||||
|
console.log(\`enter on row with index: \${rowIndex}\`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,7 +56,7 @@ const rowEvents = {
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Try to click on any rows</h3>
|
<h3>Try to click or hover on any rows</h3>
|
||||||
<BootstrapTable keyField="id" data={ products } columns={ columns } rowEvents={ rowEvents } />
|
<BootstrapTable keyField="id" data={ products } columns={ columns } rowEvents={ rowEvents } />
|
||||||
<Code>{ sourceCode }</Code>
|
<Code>{ sourceCode }</Code>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
57
packages/react-bootstrap-table2-example/examples/rows/row-hidden.js
vendored
Normal file
57
packages/react-bootstrap-table2-example/examples/rows/row-hidden.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-console: 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'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const rowEvents = {
|
||||||
|
onClick: (e, row, rowIndex) => {
|
||||||
|
console.log(`clicked on row with index: ${rowIndex}`);
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, row, rowIndex) => {
|
||||||
|
console.log(`enter on row with index: ${rowIndex}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const hiddenRowKeys = [1, 3];
|
||||||
|
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
const hiddenRowKeys = [1, 3];
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
83
packages/react-bootstrap-table2-example/examples/search/default-search.js
vendored
Normal file
83
packages/react-bootstrap-table2-example/examples/search/default-search.js
vendored
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/* 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 } = 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 } = 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={ { defaultSearch: '2101' } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<h3>Input something at below input field:</h3>
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
search={ { defaultSearch: '2101' } }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props => (
|
||||||
|
<div>
|
||||||
|
<h3>Input something at below input field:</h3>
|
||||||
|
<SearchBar { ...props.searchProps } />
|
||||||
|
<hr />
|
||||||
|
<BootstrapTable
|
||||||
|
{ ...props.baseProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</ToolkitProvider>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
59
packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js
vendored
Normal file
59
packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/* 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',
|
||||||
|
sort: true
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
sort: true,
|
||||||
|
sortCaret: (order, column) => {
|
||||||
|
if (!order) return (<span> Desc/Asc</span>);
|
||||||
|
else if (order === 'asc') return (<span> Desc/<font color="red">Asc</font></span>);
|
||||||
|
else if (order === 'desc') return (<span> <font color="red">Desc</font>/Asc</span>);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID',
|
||||||
|
sort: true
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name',
|
||||||
|
sort: true,
|
||||||
|
sortCaret: (order, column) => {
|
||||||
|
if (!order) return (<span> Desc/Asc</span>);
|
||||||
|
else if (order === 'asc') return (<span> Desc/<font color="red">Asc</font></span>);
|
||||||
|
else if (order === 'desc') return (<span> <font color="red">Desc</font>/Asc</span>);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Typed from 'typed.js';
|
import Typed from 'typed.js';
|
||||||
|
|
||||||
|
const PROJECT_NAME = 'react-bootstrap-table2';
|
||||||
|
|
||||||
export default class Welcome extends React.Component {
|
export default class Welcome extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// type.js config
|
// type.js config
|
||||||
@@ -21,14 +23,21 @@ export default class Welcome extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="welcome">
|
<div className="welcome">
|
||||||
<h1 className="welcome-title">react-bootstrap-table2</h1>
|
<div className="welcome-title">
|
||||||
|
<span className="welcome-title-logo">
|
||||||
|
<img src="images/logo-color-square.svg" alt={ `${PROJECT_NAME}-logo` } />
|
||||||
|
</span>
|
||||||
|
<h1>
|
||||||
|
{PROJECT_NAME}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
className="welcome-sub-title"
|
className="welcome-sub-title"
|
||||||
ref={ (el) => { this.el = el; } }
|
ref={ (el) => { this.el = el; } }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<a href="https://github.com/react-bootstrap-table/react-bootstrap-table2" className="github-corner" aria-label="View source on Github">
|
<a href={ `https://github.com/react-bootstrap-table/${PROJECT_NAME}` } className="github-corner" aria-label="View source on Github">
|
||||||
<svg width="80" height="80" viewBox="0 0 250 250" style={ { fill: '#009688', color: '#fff', position: 'absolute', top: '0', border: '0', right: '0' } } aria-hidden="true">
|
<svg width="80" height="80" viewBox="0 0 250 250" style={ { fill: '#0058B7', color: '#fff', position: 'absolute', top: '0', border: '0', right: '0' } } aria-hidden="true">
|
||||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
|
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
|
||||||
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style={ { transformOrigin: '130px 106px' } } className="octo-arm" />
|
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style={ { transformOrigin: '130px 106px' } } className="octo-arm" />
|
||||||
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" className="octo-body" />
|
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" className="octo-body" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-example",
|
"name": "react-bootstrap-table2-example",
|
||||||
"version": "1.0.3",
|
"version": "1.0.13",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"prop-types": "^15.0.0",
|
"prop-types": "^15.0.0",
|
||||||
"react": "^16.3.0",
|
"react": "^16.3.0",
|
||||||
"react-dom": "^116.3.0"
|
"react-dom": "^16.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@storybook/addon-console": "^1.0.0",
|
"@storybook/addon-console": "^1.0.0",
|
||||||
|
|||||||
BIN
packages/react-bootstrap-table2-example/public/favicon.ico
Normal file
BIN
packages/react-bootstrap-table2-example/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg id="layer_1" data-name="layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72"><defs><style>.cls-1{fill:#059ae6;}.cls-2{fill:#0058b7;}</style></defs><title>logo square</title><polygon class="cls-1" points="22.76 59 22.76 64.35 49.24 51.13 49.24 43.88 44.45 41.5 44.45 48.17 22.76 59"/><polygon class="cls-2" points="22.76 20.87 22.76 47.98 27.55 45.59 27.55 23.83 44.45 15.39 44.45 23.02 33.06 28.71 33.06 31.9 49.24 39.97 49.24 34.62 40.58 30.3 49.24 25.98 49.24 7.65 22.76 20.87"/></svg>
|
||||||
|
After Width: | Height: | Size: 503 B |
@@ -1,4 +1,5 @@
|
|||||||
/* eslint no-mixed-operators: 0 */
|
/* eslint no-mixed-operators: 0 */
|
||||||
|
/* eslint no-param-reassign: 0 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* products generator for stories
|
* products generator for stories
|
||||||
@@ -22,6 +23,12 @@ export const productsGenerator = (quantity = 5, callback) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const withOnSale = rows => rows.map((row) => {
|
||||||
|
if (row.id > 2) row.onSale = false;
|
||||||
|
else row.onSale = true;
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
|
||||||
export const productsQualityGenerator = (quantity = 5) =>
|
export const productsQualityGenerator = (quantity = 5) =>
|
||||||
Array.from({ length: quantity }, (value, index) => ({
|
Array.from({ length: quantity }, (value, index) => ({
|
||||||
id: index,
|
id: index,
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import NoDataTable from 'examples/basic/no-data-table';
|
|||||||
import CustomizedIdClassesTable from 'examples/basic/customized-id-classes';
|
import CustomizedIdClassesTable from 'examples/basic/customized-id-classes';
|
||||||
import CaptionTable from 'examples/basic/caption-table';
|
import CaptionTable from 'examples/basic/caption-table';
|
||||||
import LargeTable from 'examples/basic/large-table';
|
import LargeTable from 'examples/basic/large-table';
|
||||||
|
import ExposedAPITable from 'examples/basic/exposed-function';
|
||||||
|
import TabIndexCellTable from 'examples/basic/tabindex-column';
|
||||||
|
|
||||||
// bootstrap 4
|
// bootstrap 4
|
||||||
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
|
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
|
||||||
@@ -30,6 +32,7 @@ import ColumnTitleTable from 'examples/columns/column-title-table';
|
|||||||
import ColumnEventTable from 'examples/columns/column-event-table';
|
import ColumnEventTable from 'examples/columns/column-event-table';
|
||||||
import ColumnHiddenTable from 'examples/columns/column-hidden-table';
|
import ColumnHiddenTable from 'examples/columns/column-hidden-table';
|
||||||
import ColumnAttrsTable from 'examples/columns/column-attrs-table';
|
import ColumnAttrsTable from 'examples/columns/column-attrs-table';
|
||||||
|
import DummyColumnTable from 'examples/columns/dummy-column-table';
|
||||||
|
|
||||||
// work on header columns
|
// work on header columns
|
||||||
import HeaderColumnFormatTable from 'examples/header-columns/column-format-table';
|
import HeaderColumnFormatTable from 'examples/header-columns/column-format-table';
|
||||||
@@ -52,6 +55,7 @@ import CustomFilterValue from 'examples/column-filter/custom-filter-value';
|
|||||||
import SelectFilter from 'examples/column-filter/select-filter';
|
import SelectFilter from 'examples/column-filter/select-filter';
|
||||||
import SelectFilterWithDefaultValue from 'examples/column-filter/select-filter-default-value';
|
import SelectFilterWithDefaultValue from 'examples/column-filter/select-filter-default-value';
|
||||||
import SelectFilterComparator from 'examples/column-filter/select-filter-like-comparator';
|
import SelectFilterComparator from 'examples/column-filter/select-filter-like-comparator';
|
||||||
|
import SelectFilterWithPreservedOptionsOrder from 'examples/column-filter/select-filter-preserve-option-order';
|
||||||
import CustomSelectFilter from 'examples/column-filter/custom-select-filter';
|
import CustomSelectFilter from 'examples/column-filter/custom-select-filter';
|
||||||
import MultiSelectFilter from 'examples/column-filter/multi-select-filter';
|
import MultiSelectFilter from 'examples/column-filter/multi-select-filter';
|
||||||
import MultiSelectFilterDefaultValue from 'examples/column-filter/multi-select-filter-default-value';
|
import MultiSelectFilterDefaultValue from 'examples/column-filter/multi-select-filter-default-value';
|
||||||
@@ -75,6 +79,7 @@ import ClearAllFilters from 'examples/column-filter/clear-all-filters';
|
|||||||
import RowStyleTable from 'examples/rows/row-style';
|
import RowStyleTable from 'examples/rows/row-style';
|
||||||
import RowClassTable from 'examples/rows/row-class';
|
import RowClassTable from 'examples/rows/row-class';
|
||||||
import RowEventTable from 'examples/rows/row-event';
|
import RowEventTable from 'examples/rows/row-event';
|
||||||
|
import RowHiddenTable from 'examples/rows/row-hidden';
|
||||||
|
|
||||||
// table sort
|
// table sort
|
||||||
import EnableSortTable from 'examples/sort/enable-sort-table';
|
import EnableSortTable from 'examples/sort/enable-sort-table';
|
||||||
@@ -82,6 +87,7 @@ import DefaultSortTable from 'examples/sort/default-sort-table';
|
|||||||
import DefaultSortDirectionTable from 'examples/sort/default-sort-direction';
|
import DefaultSortDirectionTable from 'examples/sort/default-sort-direction';
|
||||||
import SortEvents from 'examples/sort/sort-events';
|
import SortEvents from 'examples/sort/sort-events';
|
||||||
import CustomSortTable from 'examples/sort/custom-sort-table';
|
import CustomSortTable from 'examples/sort/custom-sort-table';
|
||||||
|
import CustomSortCaretTable from 'examples/sort/custom-sort-caret';
|
||||||
import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes';
|
import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes';
|
||||||
import HeaderSortingStyleTable from 'examples/sort/header-sorting-style';
|
import HeaderSortingStyleTable from 'examples/sort/header-sorting-style';
|
||||||
|
|
||||||
@@ -93,11 +99,15 @@ import RowLevelEditableTable from 'examples/cell-edit/row-level-editable-table';
|
|||||||
import ColumnLevelEditableTable from 'examples/cell-edit/column-level-editable-table';
|
import ColumnLevelEditableTable from 'examples/cell-edit/column-level-editable-table';
|
||||||
import CellLevelEditable from 'examples/cell-edit/cell-level-editable-table';
|
import CellLevelEditable from 'examples/cell-edit/cell-level-editable-table';
|
||||||
import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
|
import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
|
||||||
|
import AsyncCellEditHooks from 'examples/cell-edit/cell-edit-async-hooks-table';
|
||||||
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
|
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
|
||||||
|
import AsyncCellEditValidator from 'examples/cell-edit/cell-edit-async-validator-table';
|
||||||
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
|
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
|
||||||
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
|
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
|
||||||
|
import AutoSelectTextInput from 'examples/cell-edit/auto-select-text-input-table';
|
||||||
import EditorStyleTable from 'examples/cell-edit/editor-style-table';
|
import EditorStyleTable from 'examples/cell-edit/editor-style-table';
|
||||||
import EditorClassTable from 'examples/cell-edit/editor-class-table';
|
import EditorClassTable from 'examples/cell-edit/editor-class-table';
|
||||||
|
import DBClickEditWithSelection from 'examples/cell-edit/dbclick-to-edit-with-selection-table';
|
||||||
import DropdownEditorTable from 'examples/cell-edit/dropdown-editor-table';
|
import DropdownEditorTable from 'examples/cell-edit/dropdown-editor-table';
|
||||||
import TextareaEditorTable from 'examples/cell-edit/textarea-editor-table';
|
import TextareaEditorTable from 'examples/cell-edit/textarea-editor-table';
|
||||||
import CheckboxEditorTable from 'examples/cell-edit/checkbox-editor-table';
|
import CheckboxEditorTable from 'examples/cell-edit/checkbox-editor-table';
|
||||||
@@ -110,10 +120,13 @@ import MultipleSelectionTable from 'examples/row-selection/multiple-selection';
|
|||||||
import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
||||||
import DefaultSelectTable from 'examples/row-selection/default-select';
|
import DefaultSelectTable from 'examples/row-selection/default-select';
|
||||||
import SelectionManagement from 'examples/row-selection/selection-management';
|
import SelectionManagement from 'examples/row-selection/selection-management';
|
||||||
|
import AdvanceSelectionManagement from 'examples/row-selection/selection-advance-management';
|
||||||
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
||||||
|
import SelectionWithExpansionTable from 'examples/row-selection/selection-with-expansion';
|
||||||
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
|
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
|
||||||
import SelectionStyleTable from 'examples/row-selection/selection-style';
|
import SelectionStyleTable from 'examples/row-selection/selection-style';
|
||||||
import SelectionClassTable from 'examples/row-selection/selection-class';
|
import SelectionClassTable from 'examples/row-selection/selection-class';
|
||||||
|
import HideSelectAllTable from 'examples/row-selection/hide-select-all';
|
||||||
import CustomSelectionTable from 'examples/row-selection/custom-selection';
|
import CustomSelectionTable from 'examples/row-selection/custom-selection';
|
||||||
import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows';
|
import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows';
|
||||||
import SelectionBgColorTable from 'examples/row-selection/selection-bgcolor';
|
import SelectionBgColorTable from 'examples/row-selection/selection-bgcolor';
|
||||||
@@ -125,6 +138,8 @@ import BasicRowExpand from 'examples/row-expand';
|
|||||||
import RowExpandManagement from 'examples/row-expand/expand-management';
|
import RowExpandManagement from 'examples/row-expand/expand-management';
|
||||||
import NonExpandableRows from 'examples/row-expand/non-expandable-rows';
|
import NonExpandableRows from 'examples/row-expand/non-expandable-rows';
|
||||||
import ExpandColumn from 'examples/row-expand/expand-column';
|
import ExpandColumn from 'examples/row-expand/expand-column';
|
||||||
|
import OnlyExpandByColumn from 'examples/row-expand/expand-by-column-only.js';
|
||||||
|
import ExpandOnlyOne from 'examples/row-expand/expand-only-one';
|
||||||
import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
|
import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
|
||||||
import ExpandHooks from 'examples/row-expand/expand-hooks';
|
import ExpandHooks from 'examples/row-expand/expand-hooks';
|
||||||
|
|
||||||
@@ -132,9 +147,17 @@ import ExpandHooks from 'examples/row-expand/expand-hooks';
|
|||||||
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 CustomPaginationTable from 'examples/pagination/custom-pagination';
|
import CustomPaginationTable from 'examples/pagination/custom-pagination';
|
||||||
|
import CustomPageButtonTable from 'examples/pagination/custom-page-button';
|
||||||
|
import CustomSizePerPageOptionTable from 'examples/pagination/custom-size-per-page-option';
|
||||||
|
import CustomSizePerPageTable from 'examples/pagination/custom-size-per-page';
|
||||||
|
import CustomPageListTable from 'examples/pagination/custom-page-list';
|
||||||
|
import StandalonePaginationList from 'examples/pagination/standalone-pagination-list';
|
||||||
|
import StandaloneSizePerPage from 'examples/pagination/standalone-size-per-page';
|
||||||
|
import FullyCustomPaginationTable from 'examples/pagination/fully-custom-pagination';
|
||||||
|
|
||||||
// search
|
// search
|
||||||
import SearchTable from 'examples/search';
|
import SearchTable from 'examples/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';
|
||||||
import SearchFormattedData from 'examples/search/search-formatted';
|
import SearchFormattedData from 'examples/search/search-formatted';
|
||||||
@@ -145,8 +168,10 @@ import ExportCSV from 'examples/csv';
|
|||||||
import CSVFormatter from 'examples/csv/csv-column-formatter';
|
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 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 CustomCSV from 'examples/csv/custom-csv';
|
import CustomCSV from 'examples/csv/custom-csv';
|
||||||
|
|
||||||
// loading overlay
|
// loading overlay
|
||||||
@@ -182,7 +207,9 @@ storiesOf('Basic Table', module)
|
|||||||
.add('Indication For Empty Table', () => <NoDataTable />)
|
.add('Indication For Empty Table', () => <NoDataTable />)
|
||||||
.add('Customized id and class table', () => <CustomizedIdClassesTable />)
|
.add('Customized id and class table', () => <CustomizedIdClassesTable />)
|
||||||
.add('Table with caption', () => <CaptionTable />)
|
.add('Table with caption', () => <CaptionTable />)
|
||||||
.add('Large Table', () => <LargeTable />);
|
.add('Large Table', () => <LargeTable />)
|
||||||
|
.add('Exposed API', () => <ExposedAPITable />)
|
||||||
|
.add('Enable tabIndex on Cell', () => <TabIndexCellTable />);
|
||||||
|
|
||||||
storiesOf('Bootstrap 4', module)
|
storiesOf('Bootstrap 4', module)
|
||||||
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
|
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
|
||||||
@@ -201,7 +228,8 @@ storiesOf('Work on Columns', module)
|
|||||||
.add('Column Event', () => <ColumnEventTable />)
|
.add('Column Event', () => <ColumnEventTable />)
|
||||||
.add('Customize Column Class', () => <ColumnClassTable />)
|
.add('Customize Column Class', () => <ColumnClassTable />)
|
||||||
.add('Customize Column Style', () => <ColumnStyleTable />)
|
.add('Customize Column Style', () => <ColumnStyleTable />)
|
||||||
.add('Customize Column HTML attribute', () => <ColumnAttrsTable />);
|
.add('Customize Column HTML attribute', () => <ColumnAttrsTable />)
|
||||||
|
.add('Dummy Column', () => <DummyColumnTable />);
|
||||||
|
|
||||||
storiesOf('Work on Header Columns', module)
|
storiesOf('Work on Header Columns', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
@@ -244,12 +272,14 @@ storiesOf('Column Filter', module)
|
|||||||
.add('Programmatically Multi Select Filter', () => <ProgrammaticallyMultiSelectFilter />)
|
.add('Programmatically Multi Select Filter', () => <ProgrammaticallyMultiSelectFilter />)
|
||||||
.add('Custom Filter', () => <CustomFilter />)
|
.add('Custom Filter', () => <CustomFilter />)
|
||||||
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
||||||
|
.add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
|
||||||
.add('Clear All Filters', () => <ClearAllFilters />);
|
.add('Clear All Filters', () => <ClearAllFilters />);
|
||||||
|
|
||||||
storiesOf('Work on Rows', module)
|
storiesOf('Work on Rows', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Customize Row Style', () => <RowStyleTable />)
|
.add('Customize Row Style', () => <RowStyleTable />)
|
||||||
.add('Customize Row Class', () => <RowClassTable />)
|
.add('Customize Row Class', () => <RowClassTable />)
|
||||||
|
.add('Hide Rows', () => <RowHiddenTable />)
|
||||||
.add('Row Event', () => <RowEventTable />);
|
.add('Row Event', () => <RowEventTable />);
|
||||||
|
|
||||||
storiesOf('Sort Table', module)
|
storiesOf('Sort Table', module)
|
||||||
@@ -259,6 +289,7 @@ storiesOf('Sort Table', module)
|
|||||||
.add('Default Sort Direction Table', () => <DefaultSortDirectionTable />)
|
.add('Default Sort Direction Table', () => <DefaultSortDirectionTable />)
|
||||||
.add('Sort Events', () => <SortEvents />)
|
.add('Sort Events', () => <SortEvents />)
|
||||||
.add('Custom Sort Fuction', () => <CustomSortTable />)
|
.add('Custom Sort Fuction', () => <CustomSortTable />)
|
||||||
|
.add('Custom Sort Caret', () => <CustomSortCaretTable />)
|
||||||
.add('Custom Classes on Sorting Header Column', () => <HeaderSortingClassesTable />)
|
.add('Custom Classes on Sorting Header Column', () => <HeaderSortingClassesTable />)
|
||||||
.add('Custom Style on Sorting Header Column', () => <HeaderSortingStyleTable />);
|
.add('Custom Style on Sorting Header Column', () => <HeaderSortingStyleTable />);
|
||||||
|
|
||||||
@@ -271,11 +302,15 @@ storiesOf('Cell Editing', module)
|
|||||||
.add('Column Level Editable', () => <ColumnLevelEditableTable />)
|
.add('Column Level Editable', () => <ColumnLevelEditableTable />)
|
||||||
.add('Cell Level Editable', () => <CellLevelEditable />)
|
.add('Cell Level Editable', () => <CellLevelEditable />)
|
||||||
.add('Rich Hook Functions', () => <CellEditHooks />)
|
.add('Rich Hook Functions', () => <CellEditHooks />)
|
||||||
|
.add('Async Hook Functions', () => <AsyncCellEditHooks />)
|
||||||
.add('Validation', () => <CellEditValidator />)
|
.add('Validation', () => <CellEditValidator />)
|
||||||
|
.add('Async Validation', () => <AsyncCellEditValidator />)
|
||||||
|
.add('Auto Select Text Input', () => <AutoSelectTextInput />)
|
||||||
.add('Custom Cell Style', () => <CellEditStyleTable />)
|
.add('Custom Cell Style', () => <CellEditStyleTable />)
|
||||||
.add('Custom Cell Classes', () => <CellEditClassTable />)
|
.add('Custom Cell Classes', () => <CellEditClassTable />)
|
||||||
.add('Custom Editor Classes', () => <EditorClassTable />)
|
.add('Custom Editor Classes', () => <EditorClassTable />)
|
||||||
.add('Custom Editor Style', () => <EditorStyleTable />)
|
.add('Custom Editor Style', () => <EditorStyleTable />)
|
||||||
|
.add('DoubleClick to Edit with Selection', () => <DBClickEditWithSelection />)
|
||||||
.add('Dropdown Editor', () => <DropdownEditorTable />)
|
.add('Dropdown Editor', () => <DropdownEditorTable />)
|
||||||
.add('Textarea Editor', () => <TextareaEditorTable />)
|
.add('Textarea Editor', () => <TextareaEditorTable />)
|
||||||
.add('Checkbox Editor', () => <CheckboxEditorTable />)
|
.add('Checkbox Editor', () => <CheckboxEditorTable />)
|
||||||
@@ -289,10 +324,13 @@ storiesOf('Row Selection', module)
|
|||||||
.add('Click to Select', () => <ClickToSelectTable />)
|
.add('Click to Select', () => <ClickToSelectTable />)
|
||||||
.add('Default Select', () => <DefaultSelectTable />)
|
.add('Default Select', () => <DefaultSelectTable />)
|
||||||
.add('Selection Management', () => <SelectionManagement />)
|
.add('Selection Management', () => <SelectionManagement />)
|
||||||
|
.add('Advance Selection Management', () => <AdvanceSelectionManagement />)
|
||||||
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
||||||
|
.add('Row Select and Expand', () => <SelectionWithExpansionTable />)
|
||||||
.add('Selection without Data', () => <SelectionNoDataTable />)
|
.add('Selection without Data', () => <SelectionNoDataTable />)
|
||||||
.add('Selection Style', () => <SelectionStyleTable />)
|
.add('Selection Style', () => <SelectionStyleTable />)
|
||||||
.add('Selection Class', () => <SelectionClassTable />)
|
.add('Selection Class', () => <SelectionClassTable />)
|
||||||
|
.add('Hide Select All', () => <HideSelectAllTable />)
|
||||||
.add('Custom Selection', () => <CustomSelectionTable />)
|
.add('Custom Selection', () => <CustomSelectionTable />)
|
||||||
.add('Selection Background Color', () => <SelectionBgColorTable />)
|
.add('Selection Background Color', () => <SelectionBgColorTable />)
|
||||||
.add('Not Selectabled Rows', () => <NonSelectableRowsTable />)
|
.add('Not Selectabled Rows', () => <NonSelectableRowsTable />)
|
||||||
@@ -305,6 +343,8 @@ storiesOf('Row Expand', module)
|
|||||||
.add('Expand Management', () => <RowExpandManagement />)
|
.add('Expand Management', () => <RowExpandManagement />)
|
||||||
.add('Non Expandabled Rows', () => <NonExpandableRows />)
|
.add('Non Expandabled Rows', () => <NonExpandableRows />)
|
||||||
.add('Expand Indicator', () => <ExpandColumn />)
|
.add('Expand Indicator', () => <ExpandColumn />)
|
||||||
|
.add('Only Expand by Indicator', () => <OnlyExpandByColumn />)
|
||||||
|
.add('Expand Only One Row at The Same Time', () => <ExpandOnlyOne />)
|
||||||
.add('Custom Expand Indicator', () => <CustomExpandColumn />)
|
.add('Custom Expand Indicator', () => <CustomExpandColumn />)
|
||||||
.add('Expand Hooks', () => <ExpandHooks />);
|
.add('Expand Hooks', () => <ExpandHooks />);
|
||||||
|
|
||||||
@@ -312,11 +352,19 @@ 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('Custom Pagination', () => <CustomPaginationTable />);
|
.add('Custom Pagination', () => <CustomPaginationTable />)
|
||||||
|
.add('Custom Page Button', () => <CustomPageButtonTable />)
|
||||||
|
.add('Custom Page List', () => <CustomPageListTable />)
|
||||||
|
.add('Custom SizePerPage Option', () => <CustomSizePerPageOptionTable />)
|
||||||
|
.add('Custom SizePerPage', () => <CustomSizePerPageTable />)
|
||||||
|
.add('Standalone Pagination List', () => <StandalonePaginationList />)
|
||||||
|
.add('Standalone SizePerPage Dropdown', () => <StandaloneSizePerPage />)
|
||||||
|
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />);
|
||||||
|
|
||||||
storiesOf('Table Search', module)
|
storiesOf('Table Search', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Basic Search Table', () => <SearchTable />)
|
.add('Basic Search Table', () => <SearchTable />)
|
||||||
|
.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 />)
|
||||||
@@ -328,8 +376,10 @@ storiesOf('Export CSV', module)
|
|||||||
.add('Format CSV Column', () => <CSVFormatter />)
|
.add('Format CSV Column', () => <CSVFormatter />)
|
||||||
.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('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('Custom CSV', () => <CustomCSV />);
|
.add('Custom CSV', () => <CustomCSV />);
|
||||||
|
|
||||||
storiesOf('EmptyTableOverlay', module)
|
storiesOf('EmptyTableOverlay', module)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
$logo-size: 96px;
|
||||||
|
|
||||||
.welcome {
|
.welcome {
|
||||||
margin-top: 70px;
|
margin-top: 70px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -5,7 +7,22 @@
|
|||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
color: $grey-900;
|
color: $grey-900;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
|
||||||
|
&-logo {
|
||||||
|
position: relative;
|
||||||
|
top: -8px;
|
||||||
|
right: -12px;
|
||||||
|
|
||||||
|
width: $logo-size;
|
||||||
|
height: $logo-size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-sub-title {
|
&-sub-title {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
color: $grey-500;
|
color: $grey-500;
|
||||||
|
|||||||
@@ -115,6 +115,27 @@ const qualityFilter = selectFilter({
|
|||||||
// omit...
|
// omit...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Note, the selectOptions can be an array also:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: 0, label: 'good' },
|
||||||
|
{ value: 1, label: 'Bad' },
|
||||||
|
{ value: 2, label: 'unknown' }
|
||||||
|
];
|
||||||
|
const columns = [
|
||||||
|
..., {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
```
|
||||||
|
|
||||||
|
The benifit is `react-bootstrap-table2` will render the select options by the order of array.
|
||||||
|
|
||||||
## MultiSelect Filter
|
## MultiSelect Filter
|
||||||
|
|
||||||
A quick example:
|
A quick example:
|
||||||
@@ -288,3 +309,4 @@ Following properties is valid in `FILTER_TYPES`:
|
|||||||
* SELECT
|
* SELECT
|
||||||
* NUMBER
|
* NUMBER
|
||||||
* DATE
|
* DATE
|
||||||
|
* MULTISELECT
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-filter",
|
"name": "react-bootstrap-table2-filter",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ import { LIKE, EQ } from '../comparison';
|
|||||||
import { FILTER_TYPE } from '../const';
|
import { FILTER_TYPE } from '../const';
|
||||||
|
|
||||||
function optionsEquals(currOpts, prevOpts) {
|
function optionsEquals(currOpts, prevOpts) {
|
||||||
|
if (Array.isArray(currOpts)) {
|
||||||
|
for (let i = 0; i < currOpts.length; i += 1) {
|
||||||
|
if (
|
||||||
|
currOpts[i].value !== prevOpts[i].value ||
|
||||||
|
currOpts[i].label !== prevOpts[i].label
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currOpts.length === prevOpts.length;
|
||||||
|
}
|
||||||
const keys = Object.keys(currOpts);
|
const keys = Object.keys(currOpts);
|
||||||
for (let i = 0; i < keys.length; i += 1) {
|
for (let i = 0; i < keys.length; i += 1) {
|
||||||
if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
|
if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
|
||||||
@@ -16,11 +27,21 @@ function optionsEquals(currOpts, prevOpts) {
|
|||||||
return Object.keys(currOpts).length === Object.keys(prevOpts).length;
|
return Object.keys(currOpts).length === Object.keys(prevOpts).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getOptionValue(options, key) {
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
const result = options
|
||||||
|
.filter(({ label }) => label === key)
|
||||||
|
.map(({ value }) => value);
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
return options[key];
|
||||||
|
}
|
||||||
|
|
||||||
class SelectFilter extends Component {
|
class SelectFilter extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.filter = this.filter.bind(this);
|
this.filter = this.filter.bind(this);
|
||||||
const isSelected = props.options[props.defaultValue] !== undefined;
|
const isSelected = getOptionValue(props.options, props.defaultValue) !== undefined;
|
||||||
this.state = { isSelected };
|
this.state = { isSelected };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +87,14 @@ class SelectFilter extends Component {
|
|||||||
<option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option>
|
<option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Object.keys(options).forEach(key =>
|
if (Array.isArray(options)) {
|
||||||
optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>)
|
options.forEach(({ value, label }) =>
|
||||||
);
|
optionTags.push(<option key={ value } value={ value }>{ label }</option>));
|
||||||
|
} else {
|
||||||
|
Object.keys(options).forEach(key =>
|
||||||
|
optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>)
|
||||||
|
);
|
||||||
|
}
|
||||||
return optionTags;
|
return optionTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +154,7 @@ class SelectFilter extends Component {
|
|||||||
SelectFilter.propTypes = {
|
SelectFilter.propTypes = {
|
||||||
onFilter: PropTypes.func.isRequired,
|
onFilter: PropTypes.func.isRequired,
|
||||||
column: PropTypes.object.isRequired,
|
column: PropTypes.object.isRequired,
|
||||||
options: PropTypes.object.isRequired,
|
options: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
|
||||||
comparator: PropTypes.oneOf([LIKE, EQ]),
|
comparator: PropTypes.oneOf([LIKE, EQ]),
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
|
|||||||
@@ -37,4 +37,188 @@ import paginationFactory from 'react-bootstrap-table2-paginator';
|
|||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
See [pagination props](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html)
|
### Basic Customization
|
||||||
|
|
||||||
|
`react-bootstrap-table2` give some simple ways to customize something like text, styling etc, following is all the props we support for basic customization:
|
||||||
|
|
||||||
|
* [paginationSize](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationpaginationsize-number)
|
||||||
|
* [sizePerPageList](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationsizeperpagelist-array)
|
||||||
|
* [withFirstAndLast](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationwithfirstandlast-bool)
|
||||||
|
* [alwaysShowAllBtns](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationalwaysshowallbtns-bool)
|
||||||
|
* [firstPageText](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationfirstpagetext-any)
|
||||||
|
* [prePageText](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationprepagetext-any)
|
||||||
|
* [nextPageText](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationnextpagetext-any)
|
||||||
|
* [lastPageText](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationlastpagetext-any)
|
||||||
|
* [firstPageTitle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationfirstpagetitle-any)
|
||||||
|
* [prePageTitle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationprepagetitle-any)
|
||||||
|
* [nextPageTitle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationnextpagetitle-any)
|
||||||
|
* [lastPageTitle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationlastpagetitle-any)
|
||||||
|
* [hideSizePerPage](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationhidesizeperpage-bool)
|
||||||
|
* [hidePageListOnlyOnePage](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationhidepagelistonlyonepage-bool)
|
||||||
|
* [showTotal](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationshowtotal-bool)
|
||||||
|
|
||||||
|
You can check [this online demo](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Pagination&selectedStory=Custom%20Pagination&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Factions%2Factions-panel) for above props usage.
|
||||||
|
|
||||||
|
### Advance Customization
|
||||||
|
|
||||||
|
Sometime, you may feel above props is not satisfied with your requirement, don't worry, we provide following renderer for each part of pagination:
|
||||||
|
|
||||||
|
* [pageListRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationpagelistrenderer-function)
|
||||||
|
* [pageButtonRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationpagebuttonrenderer-function)
|
||||||
|
* [sizePerPageRenderer](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/pagination-props.html#paginationsizeperpagerenderer-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)
|
||||||
|
|
||||||
|
### Professional
|
||||||
|
|
||||||
|
If you want to customize the pagination component completely, you may get interesting on following solution:
|
||||||
|
|
||||||
|
* 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:
|
||||||
|
|
||||||
|
#### Import PaginationProvider
|
||||||
|
|
||||||
|
```js
|
||||||
|
import paginationFactory, { PaginationProvider } from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Declare custom and totalSize in pagination option:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const paginationOption = {
|
||||||
|
custom: true,
|
||||||
|
totalSize: products.length
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Render PaginationProvider
|
||||||
|
|
||||||
|
```js
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
.....
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
`PaginationProvider` actually is a wrapper for the concumser of react context, so that now you have to get the props from context provide then render to your compoennt and `BootstrapTable`:
|
||||||
|
|
||||||
|
* `paginationProps`: this include everything about pagination, you will use it when you render standalone component or your custom component.
|
||||||
|
* `paginationTableProps`: you don't need to know about this, but you have to render this as props to `BootstrapTable`.
|
||||||
|
|
||||||
|
So far, your customization pagination is supposed to look like it:
|
||||||
|
```js
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, you have to choose, your built-in standalne components or you customize all of them by yourself:
|
||||||
|
|
||||||
|
#### Use Standalone Component
|
||||||
|
`react-bootstrap-table2-paginator` provider two standalone components:
|
||||||
|
|
||||||
|
* Size Per Page Dropdwn Standalone
|
||||||
|
* Pagination List Standalone
|
||||||
|
|
||||||
|
When render each standalone, you just need to pass the `paginationProps` props to standalone component:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import paginationFactory, { PaginationProvider, PaginationListStandalone, SizePerPageDropdownStandalone } from 'react-bootstrap-table2-paginator';
|
||||||
|
|
||||||
|
<PaginationProvider
|
||||||
|
pagination={ paginationFactory(options) }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
({
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps
|
||||||
|
}) => (
|
||||||
|
<div>
|
||||||
|
<SizePerPageDropdownStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
{ ...paginationTableProps }
|
||||||
|
/>
|
||||||
|
<PaginationListStandalone
|
||||||
|
{ ...paginationProps }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PaginationProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```js
|
||||||
|
page,
|
||||||
|
sizePerPage,
|
||||||
|
pageStartIndex,
|
||||||
|
hidePageListOnlyOnePage,
|
||||||
|
hideSizePerPage,
|
||||||
|
alwaysShowAllBtns,
|
||||||
|
withFirstAndLast,
|
||||||
|
dataSize,
|
||||||
|
sizePerPageList,
|
||||||
|
paginationSize,
|
||||||
|
showTotal,
|
||||||
|
pageListRenderer,
|
||||||
|
pageButtonRenderer,
|
||||||
|
sizePerPageRenderer,
|
||||||
|
paginationTotalRenderer,
|
||||||
|
sizePerPageOptionRenderer,
|
||||||
|
firstPageText,
|
||||||
|
prePageText,
|
||||||
|
nextPageText,
|
||||||
|
lastPageText,
|
||||||
|
prePageTitle,
|
||||||
|
nextPageTitle,
|
||||||
|
firstPageTitle,
|
||||||
|
lastPageTitle,
|
||||||
|
onPageChange,
|
||||||
|
onSizePerPageChange
|
||||||
|
```
|
||||||
|
|
||||||
|
In most of case, `page`, `sizePerPage`, `onPageChange` and `onSizePerPageChange` are most important things for developer.
|
||||||
|
|
||||||
|
* `page`: Current page.
|
||||||
|
* `sizePerPage`: Current size per page.
|
||||||
|
* `onPageChange`: Call it when you nede to change page. This function accept one number argument which indicate the new page
|
||||||
|
* `onSizePerPageChange`: Call it when you nede to change size per page. This function accept two number argument which indicate the new sizePerPage and new page
|
||||||
|
|
||||||
|
[Here](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Pagination&selectedStory=Fully%20Custom%20Pagination&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Factions%2Factions-panel) is a online example.
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
import createContext from './src/context';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import createBaseContext from './src/state-context';
|
||||||
|
import createDataContext from './src/data-context';
|
||||||
|
import PaginationListStandalone from './src/pagination-list-standalone';
|
||||||
|
import SizePerPageDropdownStandalone from './src/size-per-page-dropdown-standalone';
|
||||||
|
|
||||||
export default (options = {}) => ({
|
export default (options = {}) => ({
|
||||||
createContext,
|
createContext: createDataContext,
|
||||||
options
|
options
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { Provider, Consumer } = createBaseContext();
|
||||||
|
|
||||||
|
const CustomizableProvider = props => (
|
||||||
|
<Provider { ...props }>
|
||||||
|
<Consumer>{ paginationProps => props.children(paginationProps) }</Consumer>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
|
||||||
|
CustomizableProvider.propTypes = {
|
||||||
|
children: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PaginationProvider = CustomizableProvider;
|
||||||
|
export { PaginationListStandalone, SizePerPageDropdownStandalone };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-paginator",
|
"name": "react-bootstrap-table2-paginator",
|
||||||
"version": "1.0.2",
|
"version": "2.0.0",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -1,179 +0,0 @@
|
|||||||
/* eslint react/prop-types: 0 */
|
|
||||||
/* eslint react/require-default-props: 0 */
|
|
||||||
/* eslint no-lonely-if: 0 */
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import Const from './const';
|
|
||||||
import { BootstrapContext } from './bootstrap';
|
|
||||||
import Pagination from './pagination';
|
|
||||||
import { getByCurrPage, alignPage } from './page';
|
|
||||||
|
|
||||||
export default (
|
|
||||||
isRemotePagination,
|
|
||||||
handleRemotePageChange
|
|
||||||
) => {
|
|
||||||
const PaginationContext = React.createContext();
|
|
||||||
|
|
||||||
class PaginationProvider extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
data: PropTypes.array.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.handleChangePage = this.handleChangePage.bind(this);
|
|
||||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
|
||||||
|
|
||||||
let currPage;
|
|
||||||
let currSizePerPage;
|
|
||||||
const { options } = props.pagination;
|
|
||||||
const sizePerPageList = options.sizePerPageList || Const.SIZE_PER_PAGE_LIST;
|
|
||||||
|
|
||||||
// initialize current page
|
|
||||||
if (typeof options.page !== 'undefined') {
|
|
||||||
currPage = options.page;
|
|
||||||
} else if (typeof options.pageStartIndex !== 'undefined') {
|
|
||||||
currPage = options.pageStartIndex;
|
|
||||||
} else {
|
|
||||||
currPage = Const.PAGE_START_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize current sizePerPage
|
|
||||||
if (typeof options.sizePerPage !== 'undefined') {
|
|
||||||
currSizePerPage = options.sizePerPage;
|
|
||||||
} else if (typeof sizePerPageList[0] === 'object') {
|
|
||||||
currSizePerPage = sizePerPageList[0].value;
|
|
||||||
} else {
|
|
||||||
currSizePerPage = sizePerPageList[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currPage = currPage;
|
|
||||||
this.currSizePerPage = currSizePerPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
let needNewState = false;
|
|
||||||
let { currPage } = this;
|
|
||||||
const { currSizePerPage } = this;
|
|
||||||
const { onPageChange } = nextProps.pagination.options;
|
|
||||||
|
|
||||||
const pageStartIndex = typeof nextProps.pagination.options.pageStartIndex !== 'undefined' ?
|
|
||||||
nextProps.pagination.options.pageStartIndex : Const.PAGE_START_INDEX;
|
|
||||||
|
|
||||||
// user should align the page when the page is not fit to the data size when remote enable
|
|
||||||
if (!isRemotePagination()) {
|
|
||||||
const newPage = alignPage(nextProps.data, currPage, currSizePerPage, pageStartIndex);
|
|
||||||
if (currPage !== newPage) {
|
|
||||||
currPage = newPage;
|
|
||||||
needNewState = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needNewState) {
|
|
||||||
if (onPageChange) {
|
|
||||||
onPageChange(currPage, currSizePerPage);
|
|
||||||
}
|
|
||||||
this.currPage = currPage;
|
|
||||||
this.currSizePerPage = currSizePerPage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChangePage(currPage) {
|
|
||||||
const { currSizePerPage } = this;
|
|
||||||
const { pagination: { options } } = this.props;
|
|
||||||
|
|
||||||
if (options.onPageChange) {
|
|
||||||
options.onPageChange(currPage, currSizePerPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currPage = currPage;
|
|
||||||
|
|
||||||
if (isRemotePagination()) {
|
|
||||||
handleRemotePageChange(currPage, currSizePerPage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.forceUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChangeSizePerPage(currSizePerPage, currPage) {
|
|
||||||
const { pagination: { options } } = this.props;
|
|
||||||
|
|
||||||
if (options.onSizePerPageChange) {
|
|
||||||
options.onSizePerPageChange(currSizePerPage, currPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currPage = currPage;
|
|
||||||
this.currSizePerPage = currSizePerPage;
|
|
||||||
|
|
||||||
if (isRemotePagination()) {
|
|
||||||
handleRemotePageChange(currPage, currSizePerPage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.forceUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let { data } = this.props;
|
|
||||||
const { pagination: { options }, bootstrap4 } = this.props;
|
|
||||||
const { currPage, currSizePerPage } = this;
|
|
||||||
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
|
||||||
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
|
||||||
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
|
||||||
Const.SHOW_ALL_PAGE_BTNS : options.alwaysShowAllBtns;
|
|
||||||
const hideSizePerPage = typeof options.hideSizePerPage === 'undefined' ?
|
|
||||||
Const.HIDE_SIZE_PER_PAGE : options.hideSizePerPage;
|
|
||||||
const hidePageListOnlyOnePage = typeof options.hidePageListOnlyOnePage === 'undefined' ?
|
|
||||||
Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE : options.hidePageListOnlyOnePage;
|
|
||||||
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
|
||||||
Const.PAGE_START_INDEX : options.pageStartIndex;
|
|
||||||
|
|
||||||
data = isRemotePagination() ?
|
|
||||||
data :
|
|
||||||
getByCurrPage(
|
|
||||||
data,
|
|
||||||
currPage,
|
|
||||||
currSizePerPage,
|
|
||||||
pageStartIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PaginationContext.Provider value={ { data } }>
|
|
||||||
{ this.props.children }
|
|
||||||
<BootstrapContext.Provider value={ { bootstrap4 } }>
|
|
||||||
<Pagination
|
|
||||||
key="pagination"
|
|
||||||
dataSize={ options.totalSize || this.props.data.length }
|
|
||||||
currPage={ currPage }
|
|
||||||
currSizePerPage={ currSizePerPage }
|
|
||||||
onPageChange={ this.handleChangePage }
|
|
||||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
|
||||||
sizePerPageList={ options.sizePerPageList || Const.SIZE_PER_PAGE_LIST }
|
|
||||||
paginationSize={ options.paginationSize || Const.PAGINATION_SIZE }
|
|
||||||
pageStartIndex={ pageStartIndex }
|
|
||||||
withFirstAndLast={ withFirstAndLast }
|
|
||||||
alwaysShowAllBtns={ alwaysShowAllBtns }
|
|
||||||
hideSizePerPage={ hideSizePerPage }
|
|
||||||
hidePageListOnlyOnePage={ hidePageListOnlyOnePage }
|
|
||||||
showTotal={ options.showTotal }
|
|
||||||
paginationTotalRenderer={ options.paginationTotalRenderer }
|
|
||||||
firstPageText={ options.firstPageText || Const.FIRST_PAGE_TEXT }
|
|
||||||
prePageText={ options.prePageText || Const.PRE_PAGE_TEXT }
|
|
||||||
nextPageText={ options.nextPageText || Const.NEXT_PAGE_TEXT }
|
|
||||||
lastPageText={ options.lastPageText || Const.LAST_PAGE_TEXT }
|
|
||||||
prePageTitle={ options.prePageTitle || Const.PRE_PAGE_TITLE }
|
|
||||||
nextPageTitle={ options.nextPageTitle || Const.NEXT_PAGE_TITLE }
|
|
||||||
firstPageTitle={ options.firstPageTitle || Const.FIRST_PAGE_TITLE }
|
|
||||||
lastPageTitle={ options.lastPageTitle || Const.LAST_PAGE_TITLE }
|
|
||||||
/>
|
|
||||||
</BootstrapContext.Provider>
|
|
||||||
</PaginationContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
Provider: PaginationProvider,
|
|
||||||
Consumer: PaginationContext.Consumer
|
|
||||||
};
|
|
||||||
};
|
|
||||||
100
packages/react-bootstrap-table2-paginator/src/data-context.js
vendored
Normal file
100
packages/react-bootstrap-table2-paginator/src/data-context.js
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
/* eslint no-lonely-if: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Const from './const';
|
||||||
|
import { BootstrapContext } from './bootstrap';
|
||||||
|
import Pagination from './pagination';
|
||||||
|
import { getByCurrPage, alignPage } from './page';
|
||||||
|
import createBaseContext from './state-context';
|
||||||
|
|
||||||
|
const { Provider } = createBaseContext();
|
||||||
|
|
||||||
|
const PaginationDataContext = React.createContext();
|
||||||
|
|
||||||
|
class PaginationDataProvider extends Provider {
|
||||||
|
static propTypes = {
|
||||||
|
data: PropTypes.array.isRequired,
|
||||||
|
remoteEmitter: PropTypes.object.isRequired,
|
||||||
|
isRemotePagination: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
super.componentWillReceiveProps(nextProps);
|
||||||
|
const { currSizePerPage } = this;
|
||||||
|
const { custom, onPageChange } = nextProps.pagination.options;
|
||||||
|
|
||||||
|
const pageStartIndex = typeof nextProps.pagination.options.pageStartIndex !== 'undefined' ?
|
||||||
|
nextProps.pagination.options.pageStartIndex : Const.PAGE_START_INDEX;
|
||||||
|
|
||||||
|
// user should align the page when the page is not fit to the data size when remote enable
|
||||||
|
if (!this.isRemotePagination() && !custom) {
|
||||||
|
const newPage = alignPage(
|
||||||
|
nextProps.data.length, this.currPage, currSizePerPage, pageStartIndex);
|
||||||
|
|
||||||
|
if (this.currPage !== newPage) {
|
||||||
|
if (onPageChange) {
|
||||||
|
onPageChange(newPage, currSizePerPage);
|
||||||
|
}
|
||||||
|
this.currPage = newPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isRemotePagination = () => this.props.isRemotePagination();
|
||||||
|
|
||||||
|
renderDefaultPagination = () => {
|
||||||
|
if (!this.props.pagination.options.custom) {
|
||||||
|
const {
|
||||||
|
bootstrap4,
|
||||||
|
page: currPage,
|
||||||
|
sizePerPage: currSizePerPage,
|
||||||
|
dataSize,
|
||||||
|
...rest
|
||||||
|
} = this.getPaginationProps();
|
||||||
|
return (
|
||||||
|
<BootstrapContext.Provider value={ { bootstrap4 } }>
|
||||||
|
<Pagination
|
||||||
|
{ ...rest }
|
||||||
|
key="pagination"
|
||||||
|
dataSize={ dataSize || this.props.data.length }
|
||||||
|
currPage={ currPage }
|
||||||
|
currSizePerPage={ currSizePerPage }
|
||||||
|
/>
|
||||||
|
</BootstrapContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let { data } = this.props;
|
||||||
|
const { pagination: { options } } = this.props;
|
||||||
|
const { currPage, currSizePerPage } = this;
|
||||||
|
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||||
|
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||||
|
|
||||||
|
data = this.isRemotePagination() ?
|
||||||
|
data :
|
||||||
|
getByCurrPage(
|
||||||
|
data,
|
||||||
|
currPage,
|
||||||
|
currSizePerPage,
|
||||||
|
pageStartIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PaginationDataContext.Provider value={ { data, setRemoteEmitter: this.setRemoteEmitter } }>
|
||||||
|
{ this.props.children }
|
||||||
|
{ this.renderDefaultPagination() }
|
||||||
|
</PaginationDataContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => ({
|
||||||
|
Provider: PaginationDataProvider,
|
||||||
|
Consumer: PaginationDataContext.Consumer
|
||||||
|
});
|
||||||
@@ -20,13 +20,14 @@ class PageButton extends Component {
|
|||||||
page,
|
page,
|
||||||
title,
|
title,
|
||||||
active,
|
active,
|
||||||
disabled
|
disabled,
|
||||||
|
className
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const classes = cs({
|
const classes = cs({
|
||||||
active,
|
active,
|
||||||
disabled,
|
disabled,
|
||||||
'page-item': true
|
'page-item': true
|
||||||
});
|
}, className);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={ classes } title={ title }>
|
<li className={ classes } title={ title }>
|
||||||
@@ -41,6 +42,7 @@ PageButton.propTypes = {
|
|||||||
page: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
page: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
||||||
active: PropTypes.bool.isRequired,
|
active: PropTypes.bool.isRequired,
|
||||||
disabled: PropTypes.bool.isRequired,
|
disabled: PropTypes.bool.isRequired,
|
||||||
|
className: PropTypes.string,
|
||||||
title: PropTypes.string
|
title: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,10 @@ export default ExtendBase =>
|
|||||||
return (currPage - 1) < pageStartIndex ? pageStartIndex : currPage - 1;
|
return (currPage - 1) < pageStartIndex ? pageStartIndex : currPage - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
goToNextPage() {
|
|
||||||
const { currPage } = this.props;
|
|
||||||
const { lastPage } = this.state;
|
|
||||||
return (currPage + 1) > lastPage ? lastPage : currPage + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
initialState() {
|
initialState() {
|
||||||
const totalPages = this.calculateTotalPage();
|
const totalPages = this.calculateTotalPage();
|
||||||
const lastPage = this.calculateLastPage(totalPages);
|
const lastPage = this.calculateLastPage(totalPages);
|
||||||
return { totalPages, lastPage, dropdownOpen: false };
|
return { totalPages, lastPage };
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateTotalPage(sizePerPage = this.props.currSizePerPage, dataSize = this.props.dataSize) {
|
calculateTotalPage(sizePerPage = this.props.currSizePerPage, dataSize = this.props.dataSize) {
|
||||||
@@ -47,8 +41,9 @@ export default ExtendBase =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
calculatePages(
|
calculatePages(
|
||||||
totalPages = this.state.totalPages,
|
totalPages,
|
||||||
lastPage = this.state.lastPage) {
|
lastPage
|
||||||
|
) {
|
||||||
const {
|
const {
|
||||||
currPage,
|
currPage,
|
||||||
paginationSize,
|
paginationSize,
|
||||||
@@ -94,7 +89,7 @@ export default ExtendBase =>
|
|||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculatePageStatus(pages = [], lastPage = this.state.lastPage) {
|
calculatePageStatus(pages = [], lastPage) {
|
||||||
const {
|
const {
|
||||||
currPage,
|
currPage,
|
||||||
pageStartIndex,
|
pageStartIndex,
|
||||||
|
|||||||
@@ -18,13 +18,11 @@ const startIndex = (
|
|||||||
) => end - (sizePerPage - 1);
|
) => end - (sizePerPage - 1);
|
||||||
|
|
||||||
export const alignPage = (
|
export const alignPage = (
|
||||||
data,
|
dataSize,
|
||||||
page,
|
page,
|
||||||
sizePerPage,
|
sizePerPage,
|
||||||
pageStartIndex
|
pageStartIndex
|
||||||
) => {
|
) => {
|
||||||
const dataSize = data.length;
|
|
||||||
|
|
||||||
if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) {
|
if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) {
|
||||||
return pageStartIndex;
|
return pageStartIndex;
|
||||||
}
|
}
|
||||||
|
|||||||
77
packages/react-bootstrap-table2-paginator/src/pagination-handler.js
vendored
Normal file
77
packages/react-bootstrap-table2-paginator/src/pagination-handler.js
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import pageResolver from './page-resolver';
|
||||||
|
|
||||||
|
export default WrappedComponent =>
|
||||||
|
class PaginationHandler extends pageResolver(Component) {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.handleChangePage = this.handleChangePage.bind(this);
|
||||||
|
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||||
|
this.state = this.initialState();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const { dataSize, currSizePerPage } = nextProps;
|
||||||
|
if (currSizePerPage !== this.props.currSizePerPage || dataSize !== this.props.dataSize) {
|
||||||
|
const totalPages = this.calculateTotalPage(currSizePerPage, dataSize);
|
||||||
|
const lastPage = this.calculateLastPage(totalPages);
|
||||||
|
this.setState({ totalPages, lastPage });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChangeSizePerPage(sizePerPage) {
|
||||||
|
const { currSizePerPage, onSizePerPageChange } = this.props;
|
||||||
|
const selectedSize = typeof sizePerPage === 'string' ? parseInt(sizePerPage, 10) : sizePerPage;
|
||||||
|
let { currPage } = this.props;
|
||||||
|
if (selectedSize !== currSizePerPage) {
|
||||||
|
const newTotalPages = this.calculateTotalPage(selectedSize);
|
||||||
|
const newLastPage = this.calculateLastPage(newTotalPages);
|
||||||
|
if (currPage > newLastPage) currPage = newLastPage;
|
||||||
|
onSizePerPageChange(selectedSize, currPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChangePage(newPage) {
|
||||||
|
let page;
|
||||||
|
const {
|
||||||
|
currPage,
|
||||||
|
pageStartIndex,
|
||||||
|
prePageText,
|
||||||
|
nextPageText,
|
||||||
|
lastPageText,
|
||||||
|
firstPageText,
|
||||||
|
onPageChange
|
||||||
|
} = this.props;
|
||||||
|
const { lastPage } = this.state;
|
||||||
|
|
||||||
|
if (newPage === prePageText) {
|
||||||
|
page = this.backToPrevPage();
|
||||||
|
} else if (newPage === nextPageText) {
|
||||||
|
page = (currPage + 1) > lastPage ? lastPage : currPage + 1;
|
||||||
|
} else if (newPage === lastPageText) {
|
||||||
|
page = lastPage;
|
||||||
|
} else if (newPage === firstPageText) {
|
||||||
|
page = pageStartIndex;
|
||||||
|
} else {
|
||||||
|
page = parseInt(newPage, 10);
|
||||||
|
}
|
||||||
|
if (page !== currPage) {
|
||||||
|
onPageChange(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<WrappedComponent
|
||||||
|
{ ...this.props }
|
||||||
|
lastPage={ this.state.lastPage }
|
||||||
|
totalPages={ this.state.totalPages }
|
||||||
|
onPageChange={ this.handleChangePage }
|
||||||
|
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
24
packages/react-bootstrap-table2-paginator/src/pagination-list-adapter.js
vendored
Normal file
24
packages/react-bootstrap-table2-paginator/src/pagination-list-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 PaginationList from './pagination-list';
|
||||||
|
|
||||||
|
const paginationListAdapter = WrappedComponent =>
|
||||||
|
class PaginationListAdapter extends pageResolver(Component) {
|
||||||
|
render() {
|
||||||
|
const { lastPage, totalPages, pageButtonRenderer, onPageChange } = this.props;
|
||||||
|
const pages = this.calculatePageStatus(this.calculatePages(totalPages, lastPage), lastPage);
|
||||||
|
return (
|
||||||
|
<WrappedComponent
|
||||||
|
pageButtonRenderer={ pageButtonRenderer }
|
||||||
|
onPageChange={ onPageChange }
|
||||||
|
pages={ pages }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const PaginationListWithAdapter = paginationListAdapter(PaginationList);
|
||||||
|
export default paginationListAdapter;
|
||||||
12
packages/react-bootstrap-table2-paginator/src/pagination-list-standalone.js
vendored
Normal file
12
packages/react-bootstrap-table2-paginator/src/pagination-list-standalone.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PaginationList from './pagination-list';
|
||||||
|
import standaloneAdapter from './standalone-adapter';
|
||||||
|
import PaginationHandler from './pagination-handler';
|
||||||
|
import paginationListAdapter from './pagination-list-adapter';
|
||||||
|
|
||||||
|
const PaginationListStandalone = props => (
|
||||||
|
<PaginationList { ...props } />
|
||||||
|
);
|
||||||
|
|
||||||
|
export default
|
||||||
|
standaloneAdapter(PaginationHandler(paginationListAdapter(PaginationListStandalone)));
|
||||||
@@ -6,13 +6,21 @@ import PageButton from './page-button';
|
|||||||
const PaginatonList = props => (
|
const PaginatonList = props => (
|
||||||
<ul className="pagination react-bootstrap-table-page-btns-ul">
|
<ul className="pagination react-bootstrap-table-page-btns-ul">
|
||||||
{
|
{
|
||||||
props.pages.map(pageProps => (
|
props.pages.map((pageProps) => {
|
||||||
<PageButton
|
if (props.pageButtonRenderer) {
|
||||||
key={ pageProps.page }
|
return props.pageButtonRenderer({
|
||||||
{ ...pageProps }
|
...pageProps,
|
||||||
onPageChange={ props.onPageChange }
|
onPageChange: props.onPageChange
|
||||||
/>
|
});
|
||||||
))
|
}
|
||||||
|
return (
|
||||||
|
<PageButton
|
||||||
|
key={ pageProps.page }
|
||||||
|
{ ...pageProps }
|
||||||
|
onPageChange={ props.onPageChange }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
@@ -24,7 +32,12 @@ PaginatonList.propTypes = {
|
|||||||
disable: PropTypes.bool,
|
disable: PropTypes.bool,
|
||||||
title: PropTypes.string
|
title: PropTypes.string
|
||||||
})).isRequired,
|
})).isRequired,
|
||||||
onPageChange: PropTypes.func.isRequired
|
onPageChange: PropTypes.func.isRequired,
|
||||||
|
pageButtonRenderer: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
PaginatonList.defaultProps = {
|
||||||
|
pageButtonRenderer: null
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PaginatonList;
|
export default PaginatonList;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
const PaginationTotal = props => (
|
const PaginationTotal = props => (
|
||||||
<span className="react-bootstrap-table-pagination-total">
|
<span className="react-bootstrap-table-pagination-total">
|
||||||
Showing rows { props.from } to { props.to + 1 } of { props.dataSize }
|
Showing rows { props.from } to { props.to } of { props.dataSize }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,89 +4,13 @@ import cs from 'classnames';
|
|||||||
import React, { Component } from 'react';
|
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 SizePerPageDropDown from './size-per-page-dropdown';
|
import paginationHandler from './pagination-handler';
|
||||||
import PaginationList from './pagination-list';
|
import { SizePerPageDropdownAdapter } from './size-per-page-dropdown-adapter';
|
||||||
|
import { PaginationListWithAdapter } from './pagination-list-adapter';
|
||||||
import PaginationTotal from './pagination-total';
|
import PaginationTotal from './pagination-total';
|
||||||
import Const from './const';
|
import Const from './const';
|
||||||
|
|
||||||
class Pagination extends pageResolver(Component) {
|
class Pagination extends pageResolver(Component) {
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.closeDropDown = this.closeDropDown.bind(this);
|
|
||||||
this.toggleDropDown = this.toggleDropDown.bind(this);
|
|
||||||
this.handleChangePage = this.handleChangePage.bind(this);
|
|
||||||
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
|
||||||
this.state = this.initialState();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
const { dataSize, currSizePerPage } = nextProps;
|
|
||||||
if (currSizePerPage !== this.props.currSizePerPage || dataSize !== this.props.dataSize) {
|
|
||||||
const totalPages = this.calculateTotalPage(currSizePerPage, dataSize);
|
|
||||||
const lastPage = this.calculateLastPage(totalPages);
|
|
||||||
this.setState({ totalPages, lastPage });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleDropDown() {
|
|
||||||
const dropdownOpen = !this.state.dropdownOpen;
|
|
||||||
this.setState(() => {
|
|
||||||
return { dropdownOpen };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
closeDropDown() {
|
|
||||||
this.setState(() => {
|
|
||||||
return { dropdownOpen: false };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChangeSizePerPage(sizePerPage) {
|
|
||||||
const { currSizePerPage, onSizePerPageChange } = this.props;
|
|
||||||
const selectedSize = typeof sizePerPage === 'string' ? parseInt(sizePerPage, 10) : sizePerPage;
|
|
||||||
let { currPage } = this.props;
|
|
||||||
if (selectedSize !== currSizePerPage) {
|
|
||||||
const newTotalPages = this.calculateTotalPage(selectedSize);
|
|
||||||
const newLastPage = this.calculateLastPage(newTotalPages);
|
|
||||||
if (currPage > newLastPage) currPage = newLastPage;
|
|
||||||
onSizePerPageChange(selectedSize, currPage);
|
|
||||||
}
|
|
||||||
this.closeDropDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChangePage(newPage) {
|
|
||||||
let page;
|
|
||||||
const {
|
|
||||||
currPage,
|
|
||||||
pageStartIndex,
|
|
||||||
prePageText,
|
|
||||||
nextPageText,
|
|
||||||
lastPageText,
|
|
||||||
firstPageText,
|
|
||||||
onPageChange
|
|
||||||
// keepSizePerPageState
|
|
||||||
} = this.props;
|
|
||||||
const { lastPage } = this.state;
|
|
||||||
|
|
||||||
if (newPage === prePageText) {
|
|
||||||
page = this.backToPrevPage();
|
|
||||||
} else if (newPage === nextPageText) {
|
|
||||||
page = (currPage + 1) > lastPage ? lastPage : currPage + 1;
|
|
||||||
} else if (newPage === lastPageText) {
|
|
||||||
page = lastPage;
|
|
||||||
} else if (newPage === firstPageText) {
|
|
||||||
page = pageStartIndex;
|
|
||||||
} else {
|
|
||||||
page = parseInt(newPage, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (keepSizePerPageState) { this.closeDropDown(); }
|
|
||||||
|
|
||||||
if (page !== currPage) {
|
|
||||||
onPageChange(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultTotal = (from, to, size) => (
|
defaultTotal = (from, to, size) => (
|
||||||
<PaginationTotal
|
<PaginationTotal
|
||||||
from={ from }
|
from={ from }
|
||||||
@@ -104,17 +28,26 @@ class Pagination extends pageResolver(Component) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { totalPages, lastPage, dropdownOpen: open } = this.state;
|
|
||||||
const {
|
const {
|
||||||
showTotal,
|
showTotal,
|
||||||
dataSize,
|
dataSize,
|
||||||
|
pageListRenderer,
|
||||||
|
pageButtonRenderer,
|
||||||
paginationTotalRenderer,
|
paginationTotalRenderer,
|
||||||
|
hidePageListOnlyOnePage,
|
||||||
|
totalPages,
|
||||||
|
lastPage,
|
||||||
|
onPageChange,
|
||||||
sizePerPageList,
|
sizePerPageList,
|
||||||
currSizePerPage,
|
currSizePerPage,
|
||||||
hideSizePerPage,
|
hideSizePerPage,
|
||||||
hidePageListOnlyOnePage
|
sizePerPageRenderer,
|
||||||
|
sizePerPageOptionRenderer,
|
||||||
|
onSizePerPageChange,
|
||||||
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const pages = this.calculatePageStatus(this.calculatePages(totalPages), lastPage);
|
|
||||||
|
const pages = this.calculatePageStatus(this.calculatePages(totalPages, lastPage), lastPage);
|
||||||
const [from, to] = this.calculateFromTo();
|
const [from, to] = this.calculateFromTo();
|
||||||
const pageListClass = cs(
|
const pageListClass = cs(
|
||||||
'react-bootstrap-table-pagination-list',
|
'react-bootstrap-table-pagination-list',
|
||||||
@@ -124,19 +57,14 @@ 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
|
||||||
sizePerPageList.length > 1 && !hideSizePerPage ?
|
sizePerPageList={ sizePerPageList }
|
||||||
(
|
currSizePerPage={ currSizePerPage }
|
||||||
<SizePerPageDropDown
|
hideSizePerPage={ hideSizePerPage }
|
||||||
currSizePerPage={ `${currSizePerPage}` }
|
sizePerPageRenderer={ sizePerPageRenderer }
|
||||||
options={ this.calculateSizePerPageStatus() }
|
sizePerPageOptionRenderer={ sizePerPageOptionRenderer }
|
||||||
onSizePerPageChange={ this.handleChangeSizePerPage }
|
onSizePerPageChange={ onSizePerPageChange }
|
||||||
onClick={ this.toggleDropDown }
|
/>
|
||||||
onBlur={ this.closeDropDown }
|
|
||||||
open={ open }
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
showTotal ?
|
showTotal ?
|
||||||
this.setTotal(
|
this.setTotal(
|
||||||
@@ -147,9 +75,22 @@ class Pagination extends pageResolver(Component) {
|
|||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className={ pageListClass }>
|
{
|
||||||
<PaginationList pages={ pages } onPageChange={ this.handleChangePage } />
|
pageListRenderer ? pageListRenderer({
|
||||||
</div>
|
pages,
|
||||||
|
onPageChange
|
||||||
|
}) : (
|
||||||
|
<div className={ pageListClass }>
|
||||||
|
<PaginationListWithAdapter
|
||||||
|
{ ...rest }
|
||||||
|
lastPage={ lastPage }
|
||||||
|
totalPages={ totalPages }
|
||||||
|
pageButtonRenderer={ pageButtonRenderer }
|
||||||
|
onPageChange={ onPageChange }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -165,7 +106,11 @@ Pagination.propTypes = {
|
|||||||
pageStartIndex: PropTypes.number,
|
pageStartIndex: PropTypes.number,
|
||||||
paginationSize: PropTypes.number,
|
paginationSize: PropTypes.number,
|
||||||
showTotal: PropTypes.bool,
|
showTotal: PropTypes.bool,
|
||||||
|
pageListRenderer: PropTypes.func,
|
||||||
|
pageButtonRenderer: PropTypes.func,
|
||||||
|
sizePerPageRenderer: PropTypes.func,
|
||||||
paginationTotalRenderer: PropTypes.func,
|
paginationTotalRenderer: PropTypes.func,
|
||||||
|
sizePerPageOptionRenderer: PropTypes.func,
|
||||||
firstPageText: PropTypes.string,
|
firstPageText: PropTypes.string,
|
||||||
prePageText: PropTypes.string,
|
prePageText: PropTypes.string,
|
||||||
nextPageText: PropTypes.string,
|
nextPageText: PropTypes.string,
|
||||||
@@ -186,7 +131,11 @@ Pagination.defaultProps = {
|
|||||||
withFirstAndLast: Const.With_FIRST_AND_LAST,
|
withFirstAndLast: Const.With_FIRST_AND_LAST,
|
||||||
alwaysShowAllBtns: Const.SHOW_ALL_PAGE_BTNS,
|
alwaysShowAllBtns: Const.SHOW_ALL_PAGE_BTNS,
|
||||||
showTotal: Const.SHOW_TOTAL,
|
showTotal: Const.SHOW_TOTAL,
|
||||||
|
pageListRenderer: null,
|
||||||
|
pageButtonRenderer: null,
|
||||||
|
sizePerPageRenderer: null,
|
||||||
paginationTotalRenderer: Const.PAGINATION_TOTAL,
|
paginationTotalRenderer: Const.PAGINATION_TOTAL,
|
||||||
|
sizePerPageOptionRenderer: null,
|
||||||
firstPageText: Const.FIRST_PAGE_TEXT,
|
firstPageText: Const.FIRST_PAGE_TEXT,
|
||||||
prePageText: Const.PRE_PAGE_TEXT,
|
prePageText: Const.PRE_PAGE_TEXT,
|
||||||
nextPageText: Const.NEXT_PAGE_TEXT,
|
nextPageText: Const.NEXT_PAGE_TEXT,
|
||||||
@@ -200,4 +149,4 @@ Pagination.defaultProps = {
|
|||||||
hidePageListOnlyOnePage: Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE
|
hidePageListOnlyOnePage: Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Pagination;
|
export default paginationHandler(Pagination);
|
||||||
|
|||||||
67
packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-adapter.js
vendored
Normal file
67
packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-adapter.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import pageResolver from './page-resolver';
|
||||||
|
import SizePerPageDropDown from './size-per-page-dropdown';
|
||||||
|
|
||||||
|
const sizePerPageDropdownAdapter = WrappedComponent =>
|
||||||
|
class SizePerPageDropdownAdapter extends pageResolver(Component) {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.closeDropDown = this.closeDropDown.bind(this);
|
||||||
|
this.toggleDropDown = this.toggleDropDown.bind(this);
|
||||||
|
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||||
|
this.state = { dropdownOpen: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDropDown() {
|
||||||
|
const dropdownOpen = !this.state.dropdownOpen;
|
||||||
|
this.setState(() => ({ dropdownOpen }));
|
||||||
|
}
|
||||||
|
|
||||||
|
closeDropDown() {
|
||||||
|
this.setState(() => ({ dropdownOpen: false }));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChangeSizePerPage(sizePerPage) {
|
||||||
|
this.props.onSizePerPageChange(sizePerPage);
|
||||||
|
this.closeDropDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
sizePerPageList,
|
||||||
|
currSizePerPage,
|
||||||
|
hideSizePerPage,
|
||||||
|
sizePerPageRenderer,
|
||||||
|
sizePerPageOptionRenderer
|
||||||
|
} = this.props;
|
||||||
|
const { dropdownOpen: open } = this.state;
|
||||||
|
|
||||||
|
if (sizePerPageList.length > 1 && !hideSizePerPage) {
|
||||||
|
if (sizePerPageRenderer) {
|
||||||
|
return sizePerPageRenderer({
|
||||||
|
options: this.calculateSizePerPageStatus(),
|
||||||
|
currSizePerPage: `${currSizePerPage}`,
|
||||||
|
onSizePerPageChange: this.handleChangeSizePerPage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<WrappedComponent
|
||||||
|
currSizePerPage={ `${currSizePerPage}` }
|
||||||
|
options={ this.calculateSizePerPageStatus() }
|
||||||
|
optionRenderer={ sizePerPageOptionRenderer }
|
||||||
|
onSizePerPageChange={ this.handleChangeSizePerPage }
|
||||||
|
onClick={ this.toggleDropDown }
|
||||||
|
onBlur={ this.closeDropDown }
|
||||||
|
open={ open }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const SizePerPageDropdownAdapter = sizePerPageDropdownAdapter(SizePerPageDropDown);
|
||||||
|
export default sizePerPageDropdownAdapter;
|
||||||
12
packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-standalone.js
vendored
Normal file
12
packages/react-bootstrap-table2-paginator/src/size-per-page-dropdown-standalone.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import SizePerPageDropdown from './size-per-page-dropdown';
|
||||||
|
import standaloneAdapter from './standalone-adapter';
|
||||||
|
import paginationHandler from './pagination-handler';
|
||||||
|
import sizePerPageDropdownAdapter from './size-per-page-dropdown-adapter';
|
||||||
|
|
||||||
|
const SizePerPageDropdownStandalone = props => (
|
||||||
|
<SizePerPageDropdown { ...props } />
|
||||||
|
);
|
||||||
|
|
||||||
|
export default
|
||||||
|
standaloneAdapter(paginationHandler(sizePerPageDropdownAdapter(SizePerPageDropdownStandalone)));
|
||||||
@@ -16,6 +16,7 @@ const SizePerPageDropDown = (props) => {
|
|||||||
className,
|
className,
|
||||||
variation,
|
variation,
|
||||||
btnContextual,
|
btnContextual,
|
||||||
|
optionRenderer,
|
||||||
currSizePerPage,
|
currSizePerPage,
|
||||||
onSizePerPageChange
|
onSizePerPageChange
|
||||||
} = props;
|
} = props;
|
||||||
@@ -61,14 +62,22 @@ const SizePerPageDropDown = (props) => {
|
|||||||
aria-labelledby="pageDropDown"
|
aria-labelledby="pageDropDown"
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
options.map(option => (
|
options.map((option) => {
|
||||||
<SizePerPageOption
|
if (optionRenderer) {
|
||||||
{ ...option }
|
return optionRenderer({
|
||||||
key={ option.text }
|
...option,
|
||||||
bootstrap4={ bootstrap4 }
|
onSizePerPageChange
|
||||||
onSizePerPageChange={ onSizePerPageChange }
|
});
|
||||||
/>
|
}
|
||||||
))
|
return (
|
||||||
|
<SizePerPageOption
|
||||||
|
{ ...option }
|
||||||
|
key={ option.text }
|
||||||
|
bootstrap4={ bootstrap4 }
|
||||||
|
onSizePerPageChange={ onSizePerPageChange }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
@@ -88,14 +97,16 @@ SizePerPageDropDown.propTypes = {
|
|||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
btnContextual: PropTypes.string,
|
btnContextual: PropTypes.string,
|
||||||
variation: PropTypes.oneOf(['dropdown', 'dropup']),
|
variation: PropTypes.oneOf(['dropdown', 'dropup']),
|
||||||
className: PropTypes.string
|
className: PropTypes.string,
|
||||||
|
optionRenderer: PropTypes.func
|
||||||
};
|
};
|
||||||
SizePerPageDropDown.defaultProps = {
|
SizePerPageDropDown.defaultProps = {
|
||||||
open: false,
|
open: false,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
btnContextual: 'btn-default btn-secondary',
|
btnContextual: 'btn-default btn-secondary',
|
||||||
variation: 'dropdown',
|
variation: 'dropdown',
|
||||||
className: ''
|
className: '',
|
||||||
|
optionRenderer: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
14
packages/react-bootstrap-table2-paginator/src/standalone-adapter.js
vendored
Normal file
14
packages/react-bootstrap-table2-paginator/src/standalone-adapter.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default WrappedComponent => ({
|
||||||
|
page,
|
||||||
|
sizePerPage,
|
||||||
|
...rest
|
||||||
|
}) => (
|
||||||
|
<WrappedComponent
|
||||||
|
{ ...rest }
|
||||||
|
currPage={ page }
|
||||||
|
currSizePerPage={ sizePerPage }
|
||||||
|
/>
|
||||||
|
);
|
||||||
169
packages/react-bootstrap-table2-paginator/src/state-context.js
vendored
Normal file
169
packages/react-bootstrap-table2-paginator/src/state-context.js
vendored
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/* eslint react/prop-types: 0 */
|
||||||
|
/* eslint react/require-default-props: 0 */
|
||||||
|
/* eslint no-lonely-if: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import Const from './const';
|
||||||
|
|
||||||
|
const StateContext = React.createContext();
|
||||||
|
|
||||||
|
class StateProvider extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.handleChangePage = this.handleChangePage.bind(this);
|
||||||
|
this.handleChangeSizePerPage = this.handleChangeSizePerPage.bind(this);
|
||||||
|
|
||||||
|
let currPage;
|
||||||
|
let currSizePerPage;
|
||||||
|
const { options } = props.pagination;
|
||||||
|
const sizePerPageList = options.sizePerPageList || Const.SIZE_PER_PAGE_LIST;
|
||||||
|
|
||||||
|
// initialize current page
|
||||||
|
if (typeof options.page !== 'undefined') {
|
||||||
|
currPage = options.page;
|
||||||
|
} else if (typeof options.pageStartIndex !== 'undefined') {
|
||||||
|
currPage = options.pageStartIndex;
|
||||||
|
} else {
|
||||||
|
currPage = Const.PAGE_START_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize current sizePerPage
|
||||||
|
if (typeof options.sizePerPage !== 'undefined') {
|
||||||
|
currSizePerPage = options.sizePerPage;
|
||||||
|
} else if (typeof sizePerPageList[0] === 'object') {
|
||||||
|
currSizePerPage = sizePerPageList[0].value;
|
||||||
|
} else {
|
||||||
|
currSizePerPage = sizePerPageList[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currPage = currPage;
|
||||||
|
this.currSizePerPage = currSizePerPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const { custom } = nextProps.pagination.options;
|
||||||
|
|
||||||
|
// user should align the page when the page is not fit to the data size when remote enable
|
||||||
|
if (this.isRemotePagination() || custom) {
|
||||||
|
this.currPage = nextProps.pagination.options.page;
|
||||||
|
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPaginationProps = () => {
|
||||||
|
const { pagination: { options }, bootstrap4 } = this.props;
|
||||||
|
const { currPage, currSizePerPage } = this;
|
||||||
|
const withFirstAndLast = typeof options.withFirstAndLast === 'undefined' ?
|
||||||
|
Const.With_FIRST_AND_LAST : options.withFirstAndLast;
|
||||||
|
const alwaysShowAllBtns = typeof options.alwaysShowAllBtns === 'undefined' ?
|
||||||
|
Const.SHOW_ALL_PAGE_BTNS : options.alwaysShowAllBtns;
|
||||||
|
const hideSizePerPage = typeof options.hideSizePerPage === 'undefined' ?
|
||||||
|
Const.HIDE_SIZE_PER_PAGE : options.hideSizePerPage;
|
||||||
|
const hidePageListOnlyOnePage = typeof options.hidePageListOnlyOnePage === 'undefined' ?
|
||||||
|
Const.HIDE_PAGE_LIST_ONLY_ONE_PAGE : options.hidePageListOnlyOnePage;
|
||||||
|
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
|
||||||
|
Const.PAGE_START_INDEX : options.pageStartIndex;
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
bootstrap4,
|
||||||
|
page: currPage,
|
||||||
|
sizePerPage: currSizePerPage,
|
||||||
|
pageStartIndex,
|
||||||
|
hidePageListOnlyOnePage,
|
||||||
|
hideSizePerPage,
|
||||||
|
alwaysShowAllBtns,
|
||||||
|
withFirstAndLast,
|
||||||
|
dataSize: options.totalSize,
|
||||||
|
sizePerPageList: options.sizePerPageList || Const.SIZE_PER_PAGE_LIST,
|
||||||
|
paginationSize: options.paginationSize || Const.PAGINATION_SIZE,
|
||||||
|
showTotal: options.showTotal,
|
||||||
|
pageListRenderer: options.pageListRenderer,
|
||||||
|
pageButtonRenderer: options.pageButtonRenderer,
|
||||||
|
sizePerPageRenderer: options.sizePerPageRenderer,
|
||||||
|
paginationTotalRenderer: options.paginationTotalRenderer,
|
||||||
|
sizePerPageOptionRenderer: options.sizePerPageOptionRenderer,
|
||||||
|
firstPageText: options.firstPageText || Const.FIRST_PAGE_TEXT,
|
||||||
|
prePageText: options.prePageText || Const.PRE_PAGE_TEXT,
|
||||||
|
nextPageText: options.nextPageText || Const.NEXT_PAGE_TEXT,
|
||||||
|
lastPageText: options.lastPageText || Const.LAST_PAGE_TEXT,
|
||||||
|
prePageTitle: options.prePageTitle || Const.PRE_PAGE_TITLE,
|
||||||
|
nextPageTitle: options.nextPageTitle || Const.NEXT_PAGE_TITLE,
|
||||||
|
firstPageTitle: options.firstPageTitle || Const.FIRST_PAGE_TITLE,
|
||||||
|
lastPageTitle: options.lastPageTitle || Const.LAST_PAGE_TITLE,
|
||||||
|
onPageChange: this.handleChangePage,
|
||||||
|
onSizePerPageChange: this.handleChangeSizePerPage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setPaginationRemoteEmitter = (remoteEmitter) => {
|
||||||
|
this.remoteEmitter = remoteEmitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPaginationRemoteEmitter = () => this.remoteEmitter || this.props.remoteEmitter;
|
||||||
|
|
||||||
|
isRemotePagination = () => {
|
||||||
|
const e = {};
|
||||||
|
this.remoteEmitter.emit('isRemotePagination', e);
|
||||||
|
return e.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChangePage(currPage) {
|
||||||
|
const { currSizePerPage } = this;
|
||||||
|
const { pagination: { options } } = this.props;
|
||||||
|
|
||||||
|
if (options.onPageChange) {
|
||||||
|
options.onPageChange(currPage, currSizePerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currPage = currPage;
|
||||||
|
|
||||||
|
if (this.isRemotePagination()) {
|
||||||
|
this.getPaginationRemoteEmitter().emit('paginationChange', currPage, currSizePerPage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChangeSizePerPage(currSizePerPage, currPage) {
|
||||||
|
const { pagination: { options } } = this.props;
|
||||||
|
|
||||||
|
if (options.onSizePerPageChange) {
|
||||||
|
options.onSizePerPageChange(currSizePerPage, currPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currPage = currPage;
|
||||||
|
this.currSizePerPage = currSizePerPage;
|
||||||
|
|
||||||
|
if (this.isRemotePagination()) {
|
||||||
|
this.getPaginationRemoteEmitter().emit('paginationChange', currPage, currSizePerPage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const paginationProps = this.getPaginationProps();
|
||||||
|
const pagination = {
|
||||||
|
...this.props.pagination,
|
||||||
|
options: paginationProps
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StateContext.Provider
|
||||||
|
value={ {
|
||||||
|
paginationProps,
|
||||||
|
paginationTableProps: {
|
||||||
|
pagination,
|
||||||
|
setPaginationRemoteEmitter: this.setPaginationRemoteEmitter
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
{ this.props.children }
|
||||||
|
</StateContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => ({
|
||||||
|
Provider: StateProvider,
|
||||||
|
Consumer: StateContext.Consumer
|
||||||
|
});
|
||||||
@@ -1,690 +0,0 @@
|
|||||||
import 'jsdom-global/register';
|
|
||||||
import React from 'react';
|
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next/src/bootstrap-table';
|
|
||||||
|
|
||||||
import Pagination from '../src/pagination';
|
|
||||||
import Const from '../src/const';
|
|
||||||
import createPaginationContext from '../src/context';
|
|
||||||
import paginationFactory from '../index';
|
|
||||||
|
|
||||||
const data = [];
|
|
||||||
for (let i = 0; i < 100; i += 1) {
|
|
||||||
data.push({
|
|
||||||
id: i,
|
|
||||||
name: `itme name ${i}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('PaginationContext', () => {
|
|
||||||
let wrapper;
|
|
||||||
let PaginationContext;
|
|
||||||
|
|
||||||
const columns = [{
|
|
||||||
dataField: 'id',
|
|
||||||
text: 'ID'
|
|
||||||
}, {
|
|
||||||
dataField: 'name',
|
|
||||||
text: 'Name'
|
|
||||||
}];
|
|
||||||
|
|
||||||
const defaultPagination = { options: {} };
|
|
||||||
|
|
||||||
const mockBase = jest.fn((props => (
|
|
||||||
<BootstrapTable
|
|
||||||
keyField="id"
|
|
||||||
data={ data }
|
|
||||||
columns={ columns }
|
|
||||||
{ ...props }
|
|
||||||
/>
|
|
||||||
)));
|
|
||||||
|
|
||||||
const handleRemotePaginationChange = jest.fn();
|
|
||||||
|
|
||||||
function shallowContext(
|
|
||||||
customPagination = defaultPagination,
|
|
||||||
enableRemote = false
|
|
||||||
) {
|
|
||||||
mockBase.mockReset();
|
|
||||||
handleRemotePaginationChange.mockReset();
|
|
||||||
PaginationContext = createPaginationContext(
|
|
||||||
jest.fn().mockReturnValue(enableRemote),
|
|
||||||
handleRemotePaginationChange
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PaginationContext.Provider
|
|
||||||
pagination={ paginationFactory(customPagination) }
|
|
||||||
columns={ columns }
|
|
||||||
data={ data }
|
|
||||||
>
|
|
||||||
<PaginationContext.Consumer>
|
|
||||||
{
|
|
||||||
paginationProps => mockBase(paginationProps)
|
|
||||||
}
|
|
||||||
</PaginationContext.Consumer>
|
|
||||||
</PaginationContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('default render', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext());
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct Provider property after calling createPaginationContext', () => {
|
|
||||||
expect(PaginationContext.Provider).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct Consumer property after calling createPaginationContext', () => {
|
|
||||||
expect(PaginationContext.Consumer).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct currPage', () => {
|
|
||||||
expect(wrapper.instance().currPage).toEqual(Const.PAGE_START_INDEX);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have correct currSizePerPage', () => {
|
|
||||||
expect(wrapper.instance().currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render Pagination component correctly', () => {
|
|
||||||
expect(wrapper.length).toBe(1);
|
|
||||||
const instance = wrapper.instance();
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination).toHaveLength(1);
|
|
||||||
expect(pagination.prop('dataSize')).toEqual(data.length);
|
|
||||||
expect(pagination.prop('currPage')).toEqual(instance.currPage);
|
|
||||||
expect(pagination.prop('currSizePerPage')).toEqual(instance.currSizePerPage);
|
|
||||||
expect(pagination.prop('onPageChange')).toEqual(instance.handleChangePage);
|
|
||||||
expect(pagination.prop('onSizePerPageChange')).toEqual(instance.handleChangeSizePerPage);
|
|
||||||
expect(pagination.prop('sizePerPageList')).toEqual(Const.SIZE_PER_PAGE_LIST);
|
|
||||||
expect(pagination.prop('paginationSize')).toEqual(Const.PAGINATION_SIZE);
|
|
||||||
expect(pagination.prop('pageStartIndex')).toEqual(Const.PAGE_START_INDEX);
|
|
||||||
expect(pagination.prop('withFirstAndLast')).toEqual(Const.With_FIRST_AND_LAST);
|
|
||||||
expect(pagination.prop('alwaysShowAllBtns')).toEqual(Const.SHOW_ALL_PAGE_BTNS);
|
|
||||||
expect(pagination.prop('firstPageText')).toEqual(Const.FIRST_PAGE_TEXT);
|
|
||||||
expect(pagination.prop('prePageText')).toEqual(Const.PRE_PAGE_TEXT);
|
|
||||||
expect(pagination.prop('nextPageText')).toEqual(Const.NEXT_PAGE_TEXT);
|
|
||||||
expect(pagination.prop('lastPageText')).toEqual(Const.LAST_PAGE_TEXT);
|
|
||||||
expect(pagination.prop('firstPageTitle')).toEqual(Const.FIRST_PAGE_TITLE);
|
|
||||||
expect(pagination.prop('prePageTitle')).toEqual(Const.PRE_PAGE_TITLE);
|
|
||||||
expect(pagination.prop('nextPageTitle')).toEqual(Const.NEXT_PAGE_TITLE);
|
|
||||||
expect(pagination.prop('lastPageTitle')).toEqual(Const.LAST_PAGE_TITLE);
|
|
||||||
expect(pagination.prop('hideSizePerPage')).toEqual(Const.HIDE_SIZE_PER_PAGE);
|
|
||||||
expect(pagination.prop('hideSizePerPage')).toEqual(Const.HIDE_SIZE_PER_PAGE);
|
|
||||||
expect(pagination.prop('paginationTotalRenderer')).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should pass correct cell editing props to children element', () => {
|
|
||||||
expect(mockBase.mock.calls[0][0].data).toHaveLength(Const.SIZE_PER_PAGE_LIST[0]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('componentWillReceiveProps', () => {
|
|
||||||
let instance;
|
|
||||||
let nextProps;
|
|
||||||
|
|
||||||
describe('when nextProps.pagination.options.page is not existing', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
page: 3
|
|
||||||
}));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
wrapper.render();
|
|
||||||
nextProps = { data, pagination: defaultPagination };
|
|
||||||
instance.componentWillReceiveProps(nextProps);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set currPage', () => {
|
|
||||||
expect(instance.currPage).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when nextProps.pagination.options.sizePerPage is not existing', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
sizePerPage: Const.SIZE_PER_PAGE_LIST[2]
|
|
||||||
}));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
wrapper.render();
|
|
||||||
nextProps = { data, pagination: defaultPagination };
|
|
||||||
instance.componentWillReceiveProps(nextProps);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set currSizePerPage', () => {
|
|
||||||
expect(instance.currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[2]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when page is not align', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
page: 2
|
|
||||||
}));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
wrapper.render();
|
|
||||||
nextProps = {
|
|
||||||
data: [],
|
|
||||||
pagination: { ...defaultPagination }
|
|
||||||
};
|
|
||||||
instance.componentWillReceiveProps(nextProps);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset currPage to first page', () => {
|
|
||||||
expect(instance.currPage).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('if options.onPageChange is defined', () => {
|
|
||||||
const onPageChange = jest.fn();
|
|
||||||
beforeEach(() => {
|
|
||||||
onPageChange.mockClear();
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
page: 2
|
|
||||||
}));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
wrapper.render();
|
|
||||||
nextProps = {
|
|
||||||
data: [],
|
|
||||||
pagination: { ...defaultPagination, options: { onPageChange } }
|
|
||||||
};
|
|
||||||
instance.componentWillReceiveProps(nextProps);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call options.onPageChange correctly', () => {
|
|
||||||
expect(onPageChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(onPageChange).toHaveBeenCalledWith(instance.currPage, instance.currSizePerPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handleChangePage', () => {
|
|
||||||
let instance;
|
|
||||||
const newPage = 3;
|
|
||||||
|
|
||||||
describe('should update component correctly', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext());
|
|
||||||
instance = wrapper.instance();
|
|
||||||
jest.spyOn(instance, 'forceUpdate');
|
|
||||||
instance.handleChangePage(newPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('', () => {
|
|
||||||
expect(instance.currPage).toEqual(newPage);
|
|
||||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('if options.onPageChange is defined', () => {
|
|
||||||
const onPageChange = jest.fn();
|
|
||||||
beforeEach(() => {
|
|
||||||
onPageChange.mockClear();
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
onPageChange
|
|
||||||
}));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
jest.spyOn(instance, 'forceUpdate');
|
|
||||||
instance.handleChangePage(newPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still update component correctly', () => {
|
|
||||||
expect(instance.currPage).toEqual(newPage);
|
|
||||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call options.onPageChange correctly', () => {
|
|
||||||
expect(onPageChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(onPageChange).toHaveBeenCalledWith(newPage, instance.currSizePerPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('if remote pagination is enable', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination
|
|
||||||
}, true));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
jest.spyOn(instance, 'forceUpdate');
|
|
||||||
instance.handleChangePage(newPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still update component correctly', () => {
|
|
||||||
expect(instance.currPage).toEqual(newPage);
|
|
||||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call handleRemotePageChange correctly', () => {
|
|
||||||
expect(handleRemotePaginationChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(handleRemotePaginationChange)
|
|
||||||
.toHaveBeenCalledWith(newPage, instance.currSizePerPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handleChangeSizePerPage', () => {
|
|
||||||
let instance;
|
|
||||||
const newPage = 2;
|
|
||||||
const newSizePerPage = 15;
|
|
||||||
|
|
||||||
describe('should update component correctly', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext());
|
|
||||||
instance = wrapper.instance();
|
|
||||||
jest.spyOn(instance, 'forceUpdate');
|
|
||||||
instance.handleChangeSizePerPage(newSizePerPage, newPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('', () => {
|
|
||||||
expect(instance.currPage).toEqual(newPage);
|
|
||||||
expect(instance.currSizePerPage).toEqual(newSizePerPage);
|
|
||||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('if options.onSizePerPageChange is defined', () => {
|
|
||||||
const onSizePerPageChange = jest.fn();
|
|
||||||
beforeEach(() => {
|
|
||||||
onSizePerPageChange.mockClear();
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
onSizePerPageChange
|
|
||||||
}));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
jest.spyOn(instance, 'forceUpdate');
|
|
||||||
instance.handleChangeSizePerPage(newSizePerPage, newPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still update component correctly', () => {
|
|
||||||
expect(instance.currPage).toEqual(newPage);
|
|
||||||
expect(instance.currSizePerPage).toEqual(newSizePerPage);
|
|
||||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call options.onSizePerPageChange correctly', () => {
|
|
||||||
expect(onSizePerPageChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(onSizePerPageChange).toHaveBeenCalledWith(newSizePerPage, newPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('if remote pagination is enable', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination
|
|
||||||
}, true));
|
|
||||||
instance = wrapper.instance();
|
|
||||||
jest.spyOn(instance, 'forceUpdate');
|
|
||||||
instance.handleChangeSizePerPage(newSizePerPage, newPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still update component correctly', () => {
|
|
||||||
expect(instance.currPage).toEqual(newPage);
|
|
||||||
expect(instance.currSizePerPage).toEqual(newSizePerPage);
|
|
||||||
expect(instance.forceUpdate).toHaveBeenCalledTimes(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call handleRemotePageChange correctly', () => {
|
|
||||||
expect(handleRemotePaginationChange).toHaveBeenCalledTimes(1);
|
|
||||||
expect(handleRemotePaginationChange)
|
|
||||||
.toHaveBeenCalledWith(newPage, newSizePerPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.page is defined', () => {
|
|
||||||
const page = 3;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
page
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set correct currPage', () => {
|
|
||||||
expect(wrapper.instance().currPage).toEqual(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('currPage')).toEqual(page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.sizePerPage is defined', () => {
|
|
||||||
const sizePerPage = Const.SIZE_PER_PAGE_LIST[2];
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
sizePerPage
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set correct currSizePerPage', () => {
|
|
||||||
expect(wrapper.instance().currSizePerPage).toEqual(sizePerPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('currSizePerPage')).toEqual(sizePerPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.totalSize is defined', () => {
|
|
||||||
const totalSize = 100;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
totalSize
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('dataSize')).toEqual(totalSize);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.showTotal is defined', () => {
|
|
||||||
const showTotal = true;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
showTotal
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('showTotal')).toEqual(showTotal);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.pageStartIndex is defined', () => {
|
|
||||||
const pageStartIndex = -1;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
pageStartIndex
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('pageStartIndex')).toEqual(pageStartIndex);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.sizePerPageList is defined', () => {
|
|
||||||
const sizePerPageList = [10, 40];
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
sizePerPageList
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('sizePerPageList')).toEqual(sizePerPageList);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.paginationSize is defined', () => {
|
|
||||||
const paginationSize = 10;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
paginationSize
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('paginationSize')).toEqual(paginationSize);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.withFirstAndLast is defined', () => {
|
|
||||||
const withFirstAndLast = false;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
withFirstAndLast
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('withFirstAndLast')).toEqual(withFirstAndLast);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.alwaysShowAllBtns is defined', () => {
|
|
||||||
const alwaysShowAllBtns = true;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
alwaysShowAllBtns
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('alwaysShowAllBtns')).toEqual(alwaysShowAllBtns);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.firstPageText is defined', () => {
|
|
||||||
const firstPageText = '1st';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
firstPageText
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('firstPageText')).toEqual(firstPageText);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.prePageText is defined', () => {
|
|
||||||
const prePageText = 'PRE';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
prePageText
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('prePageText')).toEqual(prePageText);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.nextPageText is defined', () => {
|
|
||||||
const nextPageText = 'NEXT';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
nextPageText
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('nextPageText')).toEqual(nextPageText);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.lastPageText is defined', () => {
|
|
||||||
const lastPageText = 'LAST';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
lastPageText
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('lastPageText')).toEqual(lastPageText);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.firstPageTitle is defined', () => {
|
|
||||||
const firstPageTitle = '1st';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
firstPageTitle
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('firstPageTitle')).toEqual(firstPageTitle);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.prePageTitle is defined', () => {
|
|
||||||
const prePageTitle = 'PRE';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
prePageTitle
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('prePageTitle')).toEqual(prePageTitle);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.nextPageTitle is defined', () => {
|
|
||||||
const nextPageTitle = 'NEXT';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
nextPageTitle
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('nextPageTitle')).toEqual(nextPageTitle);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.lastPageTitle is defined', () => {
|
|
||||||
const lastPageTitle = 'nth';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
lastPageTitle
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('lastPageTitle')).toEqual(lastPageTitle);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.hideSizePerPage is defined', () => {
|
|
||||||
const hideSizePerPage = true;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
hideSizePerPage
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('hideSizePerPage')).toEqual(hideSizePerPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when options.hidePageListOnlyOnePage is defined', () => {
|
|
||||||
const hidePageListOnlyOnePage = true;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(shallowContext({
|
|
||||||
...defaultPagination,
|
|
||||||
hidePageListOnlyOnePage
|
|
||||||
}));
|
|
||||||
wrapper.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering Pagination correctly', () => {
|
|
||||||
const pagination = wrapper.find(Pagination);
|
|
||||||
expect(pagination.length).toBe(1);
|
|
||||||
expect(pagination.prop('hidePageListOnlyOnePage')).toEqual(hidePageListOnlyOnePage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
import 'jsdom-global/register';
|
||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
|
import paginationFactory from '../index';
|
||||||
|
import Const from '../src/const';
|
||||||
|
import createStateContext from '../src/data-context';
|
||||||
|
import Pagination from '../src/pagination';
|
||||||
|
import { getByCurrPage } from '../src/page';
|
||||||
|
|
||||||
|
const data = [];
|
||||||
|
for (let i = 0; i < 100; i += 1) {
|
||||||
|
data.push({
|
||||||
|
id: i,
|
||||||
|
name: `itme name ${i}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('PaginationDataContext', () => {
|
||||||
|
let wrapper;
|
||||||
|
let PaginationDataContext;
|
||||||
|
|
||||||
|
const defaultPagination = { options: { totalSize: data.length }, createContext: jest.fn() };
|
||||||
|
|
||||||
|
const MockComponent = () => null;
|
||||||
|
const renderMockComponent = jest.fn((props => (
|
||||||
|
<MockComponent { ...props } />
|
||||||
|
)));
|
||||||
|
|
||||||
|
const handleRemotePaginationChange = jest.fn();
|
||||||
|
|
||||||
|
function shallowContext(
|
||||||
|
customPagination = defaultPagination,
|
||||||
|
remoteEnabled = false
|
||||||
|
) {
|
||||||
|
renderMockComponent.mockReset();
|
||||||
|
handleRemotePaginationChange.mockReset();
|
||||||
|
PaginationDataContext = createStateContext();
|
||||||
|
const isRemotePagination = jest.fn().mockReturnValue(remoteEnabled);
|
||||||
|
const remoteEmitter = { emit: jest.fn() };
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PaginationDataContext.Provider
|
||||||
|
pagination={ paginationFactory(customPagination) }
|
||||||
|
data={ data }
|
||||||
|
remoteEmitter={ remoteEmitter }
|
||||||
|
isRemotePagination={ isRemotePagination }
|
||||||
|
>
|
||||||
|
<PaginationDataContext.Consumer>
|
||||||
|
{
|
||||||
|
paginationProps => renderMockComponent(paginationProps)
|
||||||
|
}
|
||||||
|
</PaginationDataContext.Consumer>
|
||||||
|
</PaginationDataContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('default render', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext());
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct Provider property after calling createPaginationDataContext', () => {
|
||||||
|
expect(PaginationDataContext.Provider).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct Consumer property after calling createPaginationDataContext', () => {
|
||||||
|
expect(PaginationDataContext.Consumer).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct currPage', () => {
|
||||||
|
expect(wrapper.instance().currPage).toEqual(Const.PAGE_START_INDEX);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct currSizePerPage', () => {
|
||||||
|
expect(wrapper.instance().currSizePerPage).toEqual(Const.SIZE_PER_PAGE_LIST[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render correct data props to childrens', () => {
|
||||||
|
const instance = wrapper.instance();
|
||||||
|
expect(renderMockComponent).toHaveBeenCalledTimes(1);
|
||||||
|
expect(renderMockComponent).toHaveBeenCalledWith({
|
||||||
|
data: getByCurrPage(
|
||||||
|
data,
|
||||||
|
instance.currPage,
|
||||||
|
instance.currSizePerPage,
|
||||||
|
Const.PAGE_START_INDEX
|
||||||
|
),
|
||||||
|
setRemoteEmitter: instance.setRemoteEmitter
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('default render', () => {
|
||||||
|
describe('when options.custom is negative', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext());
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render Pagination component correctly', () => {
|
||||||
|
const instance = wrapper.instance();
|
||||||
|
const pagination = wrapper.find(Pagination);
|
||||||
|
expect(pagination).toHaveLength(1);
|
||||||
|
|
||||||
|
expect(pagination.prop('dataSize')).toEqual(data.length);
|
||||||
|
expect(pagination.prop('currPage')).toEqual(instance.currPage);
|
||||||
|
expect(pagination.prop('currSizePerPage')).toEqual(instance.currSizePerPage);
|
||||||
|
expect(pagination.prop('onPageChange')).toEqual(instance.handleChangePage);
|
||||||
|
expect(pagination.prop('onSizePerPageChange')).toEqual(instance.handleChangeSizePerPage);
|
||||||
|
expect(pagination.prop('sizePerPageList')).toEqual(Const.SIZE_PER_PAGE_LIST);
|
||||||
|
expect(pagination.prop('paginationSize')).toEqual(Const.PAGINATION_SIZE);
|
||||||
|
expect(pagination.prop('pageStartIndex')).toEqual(Const.PAGE_START_INDEX);
|
||||||
|
expect(pagination.prop('withFirstAndLast')).toEqual(Const.With_FIRST_AND_LAST);
|
||||||
|
expect(pagination.prop('alwaysShowAllBtns')).toEqual(Const.SHOW_ALL_PAGE_BTNS);
|
||||||
|
expect(pagination.prop('firstPageText')).toEqual(Const.FIRST_PAGE_TEXT);
|
||||||
|
expect(pagination.prop('prePageText')).toEqual(Const.PRE_PAGE_TEXT);
|
||||||
|
expect(pagination.prop('nextPageText')).toEqual(Const.NEXT_PAGE_TEXT);
|
||||||
|
expect(pagination.prop('lastPageText')).toEqual(Const.LAST_PAGE_TEXT);
|
||||||
|
expect(pagination.prop('firstPageTitle')).toEqual(Const.FIRST_PAGE_TITLE);
|
||||||
|
expect(pagination.prop('prePageTitle')).toEqual(Const.PRE_PAGE_TITLE);
|
||||||
|
expect(pagination.prop('nextPageTitle')).toEqual(Const.NEXT_PAGE_TITLE);
|
||||||
|
expect(pagination.prop('lastPageTitle')).toEqual(Const.LAST_PAGE_TITLE);
|
||||||
|
expect(pagination.prop('hideSizePerPage')).toEqual(Const.HIDE_SIZE_PER_PAGE);
|
||||||
|
expect(pagination.prop('hideSizePerPage')).toEqual(Const.HIDE_SIZE_PER_PAGE);
|
||||||
|
expect(pagination.prop('paginationTotalRenderer')).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when options.custom is positive', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext({
|
||||||
|
custom: true
|
||||||
|
}));
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render Pagination component', () => {
|
||||||
|
const pagination = wrapper.find(Pagination);
|
||||||
|
expect(pagination).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when remote pagination enabled', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext({}, true));
|
||||||
|
wrapper.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('just pass data props to children', () => {
|
||||||
|
const instance = wrapper.instance();
|
||||||
|
expect(renderMockComponent).toHaveBeenCalledTimes(1);
|
||||||
|
expect(renderMockComponent).toHaveBeenCalledWith({
|
||||||
|
data: instance.props.data,
|
||||||
|
setRemoteEmitter: instance.setRemoteEmitter
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('componentWillReceiveProps', () => {
|
||||||
|
let instance;
|
||||||
|
let nextProps;
|
||||||
|
describe('when page is not align', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(shallowContext({
|
||||||
|
...defaultPagination,
|
||||||
|
page: 2
|
||||||
|
}));
|
||||||
|
instance = wrapper.instance();
|
||||||
|
wrapper.render();
|
||||||
|
nextProps = {
|
||||||
|
data: [],
|
||||||
|
pagination: { ...defaultPagination }
|
||||||
|
};
|
||||||
|
instance.componentWillReceiveProps(nextProps);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset currPage to first page', () => {
|
||||||
|
expect(instance.currPage).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if options.onPageChange is defined', () => {
|
||||||
|
const onPageChange = jest.fn();
|
||||||
|
beforeEach(() => {
|
||||||
|
onPageChange.mockClear();
|
||||||
|
wrapper = shallow(shallowContext({
|
||||||
|
...defaultPagination,
|
||||||
|
page: 2
|
||||||
|
}));
|
||||||
|
instance = wrapper.instance();
|
||||||
|
wrapper.render();
|
||||||
|
nextProps = {
|
||||||
|
data: [],
|
||||||
|
pagination: { ...defaultPagination, options: { onPageChange } }
|
||||||
|
};
|
||||||
|
instance.componentWillReceiveProps(nextProps);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call options.onPageChange correctly', () => {
|
||||||
|
expect(onPageChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onPageChange).toHaveBeenCalledWith(instance.currPage, instance.currSizePerPage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -46,8 +46,6 @@ describe('PageResolver', () => {
|
|||||||
expect(instance.state.lastPage).toBeDefined();
|
expect(instance.state.lastPage).toBeDefined();
|
||||||
expect(instance.state.lastPage).toEqual(
|
expect(instance.state.lastPage).toEqual(
|
||||||
instance.calculateLastPage(instance.state.totalPages));
|
instance.calculateLastPage(instance.state.totalPages));
|
||||||
expect(instance.state.dropdownOpen).toBeDefined();
|
|
||||||
expect(instance.state.dropdownOpen).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -81,35 +79,6 @@ describe('PageResolver', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('goToNextPage', () => {
|
|
||||||
const props = createMockProps();
|
|
||||||
|
|
||||||
describe('when props.currPage is not hitting state.lastPage', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
const mockElement = React.createElement(MockComponent, props, null);
|
|
||||||
wrapper = shallow(mockElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should getting previous page correctly', () => {
|
|
||||||
const instance = wrapper.instance();
|
|
||||||
expect(instance.goToNextPage()).toEqual(props.currPage + 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when props.currPage is hitting state.lastpage', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
props.currPage = 10;
|
|
||||||
const mockElement = React.createElement(MockComponent, props, null);
|
|
||||||
wrapper = shallow(mockElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should always getting page which must eq props.pageStartIndex', () => {
|
|
||||||
const instance = wrapper.instance();
|
|
||||||
expect(instance.goToNextPage()).toEqual(instance.state.lastPage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('calculateFromTo', () => {
|
describe('calculateFromTo', () => {
|
||||||
const props = createMockProps();
|
const props = createMockProps();
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -192,7 +161,7 @@ describe('PageResolver', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('calculatePages', () => {
|
describe('calculatePages', () => {
|
||||||
describe('calculate by state.totalPages and state.lastPage', () => {
|
describe('calculate by totalPages and lastPage', () => {
|
||||||
const props = createMockProps();
|
const props = createMockProps();
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const mockElement = React.createElement(MockComponent, props, null);
|
const mockElement = React.createElement(MockComponent, props, null);
|
||||||
@@ -201,7 +170,7 @@ describe('PageResolver', () => {
|
|||||||
|
|
||||||
it('should getting pages list correctly', () => {
|
it('should getting pages list correctly', () => {
|
||||||
const instance = wrapper.instance();
|
const instance = wrapper.instance();
|
||||||
expect(instance.calculatePages()).toEqual(
|
expect(instance.calculatePages(instance.state.totalPages, instance.state.lastPage)).toEqual(
|
||||||
[props.prePageText, 1, 2, 3, 4, 5, props.nextPageText, props.lastPageText]);
|
[props.prePageText, 1, 2, 3, 4, 5, props.nextPageText, props.lastPageText]);
|
||||||
|
|
||||||
expect(instance.calculatePages(4, 4)).toEqual(
|
expect(instance.calculatePages(4, 4)).toEqual(
|
||||||
@@ -218,7 +187,9 @@ describe('PageResolver', () => {
|
|||||||
currPages.forEach((currPage) => {
|
currPages.forEach((currPage) => {
|
||||||
props.currPage = currPage + 1;
|
props.currPage = currPage + 1;
|
||||||
wrapper = shallow(<MockComponent { ...props } />);
|
wrapper = shallow(<MockComponent { ...props } />);
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
|
|
||||||
if (props.currPage < 4) {
|
if (props.currPage < 4) {
|
||||||
expect(pageList).toEqual(
|
expect(pageList).toEqual(
|
||||||
@@ -253,7 +224,9 @@ describe('PageResolver', () => {
|
|||||||
[1, 3, 5, 8, 10].forEach((paginationSize) => {
|
[1, 3, 5, 8, 10].forEach((paginationSize) => {
|
||||||
props.paginationSize = paginationSize;
|
props.paginationSize = paginationSize;
|
||||||
wrapper = shallow(<MockComponent { ...props } />);
|
wrapper = shallow(<MockComponent { ...props } />);
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
const result = pageList.filter(p => indicators.indexOf(p) === -1);
|
const result = pageList.filter(p => indicators.indexOf(p) === -1);
|
||||||
expect(result.length).toEqual(props.paginationSize);
|
expect(result.length).toEqual(props.paginationSize);
|
||||||
});
|
});
|
||||||
@@ -267,7 +240,9 @@ describe('PageResolver', () => {
|
|||||||
[1, 2, 3, 4, 5, 6, 7].forEach((currPage) => {
|
[1, 2, 3, 4, 5, 6, 7].forEach((currPage) => {
|
||||||
props.currPage = currPage;
|
props.currPage = currPage;
|
||||||
wrapper = shallow(<MockComponent { ...props } />);
|
wrapper = shallow(<MockComponent { ...props } />);
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
expect(pageList.indexOf(props.lastPageText) > -1).toBeTruthy();
|
expect(pageList.indexOf(props.lastPageText) > -1).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -278,7 +253,9 @@ describe('PageResolver', () => {
|
|||||||
[10, 9, 8, 7, 6, 5, 4].forEach((currPage) => {
|
[10, 9, 8, 7, 6, 5, 4].forEach((currPage) => {
|
||||||
props.currPage = currPage;
|
props.currPage = currPage;
|
||||||
wrapper = shallow(<MockComponent { ...props } />);
|
wrapper = shallow(<MockComponent { ...props } />);
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
expect(pageList.indexOf(props.firstPageText) > -1).toBeTruthy();
|
expect(pageList.indexOf(props.firstPageText) > -1).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -293,7 +270,9 @@ describe('PageResolver', () => {
|
|||||||
props.currPage = currPage + 1;
|
props.currPage = currPage + 1;
|
||||||
props.withFirstAndLast = false;
|
props.withFirstAndLast = false;
|
||||||
wrapper = shallow(<MockComponent { ...props } />);
|
wrapper = shallow(<MockComponent { ...props } />);
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
expect(pageList.indexOf(props.lastPageText) > -1).toBeFalsy();
|
expect(pageList.indexOf(props.lastPageText) > -1).toBeFalsy();
|
||||||
expect(pageList.indexOf(props.firstPageText) > -1).toBeFalsy();
|
expect(pageList.indexOf(props.firstPageText) > -1).toBeFalsy();
|
||||||
});
|
});
|
||||||
@@ -311,7 +290,9 @@ describe('PageResolver', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should getting last page correctly', () => {
|
it('should getting last page correctly', () => {
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
expect(pageList).toEqual(
|
expect(pageList).toEqual(
|
||||||
[props.prePageText, -2, -1, 0, 1, 2, props.nextPageText, props.lastPageText]);
|
[props.prePageText, -2, -1, 0, 1, 2, props.nextPageText, props.lastPageText]);
|
||||||
});
|
});
|
||||||
@@ -329,7 +310,9 @@ describe('PageResolver', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should always having next and previous page indication', () => {
|
it('should always having next and previous page indication', () => {
|
||||||
const pageList = wrapper.instance().calculatePages();
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
expect(pageList.indexOf(props.nextPageText) > -1).toBeTruthy();
|
expect(pageList.indexOf(props.nextPageText) > -1).toBeTruthy();
|
||||||
expect(pageList.indexOf(props.prePageText) > -1).toBeTruthy();
|
expect(pageList.indexOf(props.prePageText) > -1).toBeTruthy();
|
||||||
});
|
});
|
||||||
@@ -345,7 +328,10 @@ describe('PageResolver', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should getting empty array', () => {
|
it('should getting empty array', () => {
|
||||||
expect(wrapper.instance().calculatePages()).toEqual([]);
|
const instance = wrapper.instance();
|
||||||
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
|
expect(pageList).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -360,7 +346,9 @@ describe('PageResolver', () => {
|
|||||||
const mockElement = React.createElement(MockComponent, props, null);
|
const mockElement = React.createElement(MockComponent, props, null);
|
||||||
wrapper = shallow(mockElement);
|
wrapper = shallow(mockElement);
|
||||||
instance = wrapper.instance();
|
instance = wrapper.instance();
|
||||||
pageStatus = instance.calculatePageStatus(instance.calculatePages());
|
const pageList = instance.calculatePages(
|
||||||
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
|
pageStatus = instance.calculatePageStatus(pageList, instance.state.lastPage);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should returning correct format for page status', () => {
|
it('should returning correct format for page status', () => {
|
||||||
@@ -388,8 +376,9 @@ describe('PageResolver', () => {
|
|||||||
const mockElement = React.createElement(MockComponent, props, null);
|
const mockElement = React.createElement(MockComponent, props, null);
|
||||||
wrapper = shallow(mockElement);
|
wrapper = shallow(mockElement);
|
||||||
instance = wrapper.instance();
|
instance = wrapper.instance();
|
||||||
const pageList = instance.calculatePages();
|
const pageList = instance.calculatePages(
|
||||||
pageStatus = instance.calculatePageStatus(pageList);
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
|
pageStatus = instance.calculatePageStatus(pageList, instance.state.lastPage);
|
||||||
|
|
||||||
expect(pageStatus.find(p => p.page === props.prePageText)).not.toBeDefined();
|
expect(pageStatus.find(p => p.page === props.prePageText)).not.toBeDefined();
|
||||||
});
|
});
|
||||||
@@ -401,8 +390,9 @@ describe('PageResolver', () => {
|
|||||||
const mockElement = React.createElement(MockComponent, props, null);
|
const mockElement = React.createElement(MockComponent, props, null);
|
||||||
wrapper = shallow(mockElement);
|
wrapper = shallow(mockElement);
|
||||||
instance = wrapper.instance();
|
instance = wrapper.instance();
|
||||||
const pageList = instance.calculatePages();
|
const pageList = instance.calculatePages(
|
||||||
pageStatus = instance.calculatePageStatus(pageList);
|
instance.state.totalPages, instance.state.lastPage);
|
||||||
|
pageStatus = instance.calculatePageStatus(pageList, instance.state.lastPage);
|
||||||
|
|
||||||
expect(pageStatus.find(p => p.page === props.nextPageText)).not.toBeDefined();
|
expect(pageStatus.find(p => p.page === props.nextPageText)).not.toBeDefined();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,29 +46,15 @@ describe('Page Functions', () => {
|
|||||||
const pageStartIndex = 1;
|
const pageStartIndex = 1;
|
||||||
const sizePerPage = 10;
|
const sizePerPage = 10;
|
||||||
const page = 3;
|
const page = 3;
|
||||||
describe('if the page does not fit the pages interval calculated from the length of store.data', () => {
|
describe('if the page does not fit the pages which calculated from the length of data', () => {
|
||||||
beforeEach(() => {
|
|
||||||
data = [];
|
|
||||||
for (let i = 0; i < 15; i += 1) {
|
|
||||||
data.push({ id: i, name: `test_name${i}` });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return pageStartIndex argument', () => {
|
it('should return pageStartIndex argument', () => {
|
||||||
expect(alignPage(data, page, sizePerPage, pageStartIndex)).toEqual(pageStartIndex);
|
expect(alignPage(15, page, sizePerPage, pageStartIndex)).toEqual(pageStartIndex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('if the length of store.data is large than the end page index', () => {
|
describe('if the length of store.data is large than the end page index', () => {
|
||||||
beforeEach(() => {
|
|
||||||
data = [];
|
|
||||||
for (let i = 0; i < 30; i += 1) {
|
|
||||||
data.push({ id: i, name: `test_name${i}` });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return current page', () => {
|
it('should return current page', () => {
|
||||||
expect(alignPage(data, page, sizePerPage, pageStartIndex)).toEqual(page);
|
expect(alignPage(30, page, sizePerPage, pageStartIndex)).toEqual(page);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
|
import paginationHandler from '../src/pagination-handler';
|
||||||
|
|
||||||
|
const MockComponent = () => null;
|
||||||
|
const MockComponentWithPaginationHandler = paginationHandler(MockComponent);
|
||||||
|
|
||||||
|
describe('paginationHandler', () => {
|
||||||
|
let wrapper;
|
||||||
|
let instance;
|
||||||
|
|
||||||
|
const createMockProps = props => ({
|
||||||
|
dataSize: 100,
|
||||||
|
sizePerPageList: [10, 20, 30, 50],
|
||||||
|
currPage: 1,
|
||||||
|
currSizePerPage: 10,
|
||||||
|
pageStartIndex: 1,
|
||||||
|
paginationSize: 5,
|
||||||
|
withFirstAndLast: true,
|
||||||
|
firstPageText: '<<',
|
||||||
|
prePageText: '<',
|
||||||
|
nextPageText: '>',
|
||||||
|
lastPageText: '>>',
|
||||||
|
alwaysShowAllBtns: false,
|
||||||
|
onPageChange: sinon.stub(),
|
||||||
|
onSizePerPageChange: sinon.stub(),
|
||||||
|
hidePageListOnlyOnePage: false,
|
||||||
|
hideSizePerPage: false,
|
||||||
|
...props
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('default pagiantion', () => {
|
||||||
|
const props = createMockProps();
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<MockComponentWithPaginationHandler { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should having correct state', () => {
|
||||||
|
expect(instance.state).toBeDefined();
|
||||||
|
expect(instance.state.totalPages).toEqual(instance.calculateTotalPage());
|
||||||
|
expect(instance.state.lastPage).toEqual(
|
||||||
|
instance.calculateLastPage(instance.state.totalPages));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should rendering PaginationList component successfully', () => {
|
||||||
|
const wrapperedComponent = wrapper.find(MockComponent);
|
||||||
|
expect(wrapperedComponent.length).toBe(1);
|
||||||
|
expect(wrapperedComponent.props().lastPage).toEqual(instance.state.lastPage);
|
||||||
|
expect(wrapperedComponent.props().totalPages).toEqual(instance.state.totalPages);
|
||||||
|
expect(wrapperedComponent.props().onPageChange).toEqual(instance.handleChangePage);
|
||||||
|
expect(wrapperedComponent.props().onSizePerPageChange)
|
||||||
|
.toEqual(instance.handleChangeSizePerPage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handleChangePage', () => {
|
||||||
|
const props = createMockProps();
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
props.currPage = 6;
|
||||||
|
wrapper = shallow(<MockComponentWithPaginationHandler { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.onPageChange.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calling props.onPageChange correctly when new page is eq props.prePageText', () => {
|
||||||
|
instance.handleChangePage(props.prePageText);
|
||||||
|
expect(props.onPageChange.callCount).toBe(1);
|
||||||
|
expect(props.onPageChange.calledWith(5)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calling props.onPageChange correctly when new page is eq props.nextPageText', () => {
|
||||||
|
instance.handleChangePage(props.nextPageText);
|
||||||
|
expect(props.onPageChange.callCount).toBe(1);
|
||||||
|
expect(props.onPageChange.calledWith(7)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calling props.onPageChange correctly when new page is eq props.lastPageText', () => {
|
||||||
|
instance.handleChangePage(props.lastPageText);
|
||||||
|
expect(props.onPageChange.callCount).toBe(1);
|
||||||
|
expect(props.onPageChange.calledWith(10)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calling props.onPageChange correctly when new page is eq props.firstPageText', () => {
|
||||||
|
instance.handleChangePage(props.firstPageText);
|
||||||
|
expect(props.onPageChange.callCount).toBe(1);
|
||||||
|
expect(props.onPageChange.calledWith(props.pageStartIndex)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calling props.onPageChange correctly when new page is a numeric page', () => {
|
||||||
|
const newPage = '8';
|
||||||
|
instance.handleChangePage(newPage);
|
||||||
|
expect(props.onPageChange.callCount).toBe(1);
|
||||||
|
expect(props.onPageChange.calledWith(parseInt(newPage, 10))).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not calling props.onPageChange correctly when page is not changed', () => {
|
||||||
|
const newPage = props.currPage;
|
||||||
|
instance.handleChangePage(newPage);
|
||||||
|
expect(props.onPageChange.callCount).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handleChangeSizePerPage', () => {
|
||||||
|
const props = createMockProps();
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<MockComponentWithPaginationHandler { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always setting state.dropdownOpen to false', () => {
|
||||||
|
instance.handleChangeSizePerPage(10);
|
||||||
|
expect(instance.state.dropdownOpen).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when new sizePerPage is same as current one', () => {
|
||||||
|
it('should not calling props.onSizePerPageChange callback', () => {
|
||||||
|
instance.handleChangeSizePerPage(10);
|
||||||
|
expect(props.onSizePerPageChange.callCount).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when new sizePerPage is diff than current one', () => {
|
||||||
|
it('should not calling props.onSizePerPageChange callback', () => {
|
||||||
|
instance.handleChangeSizePerPage(30);
|
||||||
|
expect(props.onSizePerPageChange.callCount).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and new current page is still in the new lagination list', () => {
|
||||||
|
it('should calling props.onSizePerPageChange with correct argument', () => {
|
||||||
|
expect(props.onSizePerPageChange.calledWith(30, props.currPage));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and new current page is still in the new lagination list', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(
|
||||||
|
<MockComponentWithPaginationHandler { ...createMockProps({ currPage: 10 }) } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calling props.onSizePerPageChange with correct argument', () => {
|
||||||
|
expect(props.onSizePerPageChange.calledWith(30, 4));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('componentWillReceiveProps', () => {
|
||||||
|
describe('when next props.currSizePerPage is diff than current one', () => {
|
||||||
|
const nextProps = createMockProps({ currSizePerPage: 20 });
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<MockComponentWithPaginationHandler { ...createMockProps() } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setting correct state.totalPages', () => {
|
||||||
|
instance.componentWillReceiveProps(nextProps);
|
||||||
|
expect(instance.state.totalPages).toEqual(
|
||||||
|
instance.calculateTotalPage(nextProps.currSizePerPage));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setting correct state.lastPage', () => {
|
||||||
|
instance.componentWillReceiveProps(nextProps);
|
||||||
|
const totalPages = instance.calculateTotalPage(nextProps.currSizePerPage);
|
||||||
|
expect(instance.state.lastPage).toEqual(
|
||||||
|
instance.calculateLastPage(totalPages));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when next props.dataSize is diff than current one', () => {
|
||||||
|
const nextProps = createMockProps({ dataSize: 33 });
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<MockComponentWithPaginationHandler { ...createMockProps() } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setting correct state.totalPages', () => {
|
||||||
|
instance.componentWillReceiveProps(nextProps);
|
||||||
|
expect(instance.state.totalPages).toEqual(
|
||||||
|
instance.calculateTotalPage(nextProps.currSizePerPage, nextProps.dataSize));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should setting correct state.lastPage', () => {
|
||||||
|
instance.componentWillReceiveProps(nextProps);
|
||||||
|
const totalPages = instance.calculateTotalPage(
|
||||||
|
nextProps.currSizePerPage, nextProps.dataSize);
|
||||||
|
expect(instance.state.lastPage).toEqual(
|
||||||
|
instance.calculateLastPage(totalPages));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import paginationListAdapter from '../src/pagination-list-adapter';
|
||||||
|
|
||||||
|
|
||||||
|
const MockComponent = () => null;
|
||||||
|
|
||||||
|
const PaginationListAdapter = paginationListAdapter(MockComponent);
|
||||||
|
describe('paginationListAdapter', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
totalPages: 10,
|
||||||
|
lastPage: 10,
|
||||||
|
pageButtonRenderer: jest.fn(),
|
||||||
|
onPageChange: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('render', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<PaginationListAdapter { ...props } />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const mockComponent = wrapper.find(MockComponent);
|
||||||
|
expect(mockComponent).toHaveLength(1);
|
||||||
|
expect(mockComponent.props().pages).toBeDefined();
|
||||||
|
expect(mockComponent.props().pageButtonRenderer).toBeDefined();
|
||||||
|
expect(mockComponent.props().onPageChange).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -39,4 +39,22 @@ describe('PaginationList', () => {
|
|||||||
expect(wrapper.find('ul.react-bootstrap-table-page-btns-ul').length).toBe(1);
|
expect(wrapper.find('ul.react-bootstrap-table-page-btns-ul').length).toBe(1);
|
||||||
expect(wrapper.find(PageButton).length).toBe(pages.length);
|
expect(wrapper.find(PageButton).length).toBe(pages.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when props.pageButtonRenderer is existing', () => {
|
||||||
|
const pageButtonRenderer = jest.fn().mockReturnValue(null);
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(
|
||||||
|
<PaginationList
|
||||||
|
pages={ pages }
|
||||||
|
onPageChange={ onPageChange }
|
||||||
|
pageButtonRenderer={ pageButtonRenderer }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call props.pageButtonRenderer correctly', () => {
|
||||||
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(pageButtonRenderer).toHaveBeenCalledTimes(pages.length);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { shallow } 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;
|
||||||
@@ -40,7 +41,7 @@ describe('Pagination', () => {
|
|||||||
|
|
||||||
it('should rendering correctly', () => {
|
it('should rendering correctly', () => {
|
||||||
expect(wrapper.length).toBe(1);
|
expect(wrapper.length).toBe(1);
|
||||||
expect(wrapper.hasClass('react-bootstrap-table-pagination')).toBeTruthy();
|
expect(wrapper.dive().hasClass('react-bootstrap-table-pagination')).toBeTruthy();
|
||||||
expect(wrapper.find('.react-bootstrap-table-pagination-list-hidden').length).toBe(0);
|
expect(wrapper.find('.react-bootstrap-table-pagination-list-hidden').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,50 +52,6 @@ describe('Pagination', () => {
|
|||||||
instance.calculateLastPage(instance.state.totalPages));
|
instance.calculateLastPage(instance.state.totalPages));
|
||||||
expect(instance.state.dropdownOpen).toBeFalsy();
|
expect(instance.state.dropdownOpen).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should rendering PaginationList component successfully', () => {
|
|
||||||
const paginationList = wrapper.find(PaginationList);
|
|
||||||
expect(paginationList.length).toBe(1);
|
|
||||||
expect(paginationList.prop('pages')).toEqual(instance.calculatePageStatus(instance.calculatePages()));
|
|
||||||
expect(paginationList.prop('onPageChange')).toEqual(instance.handleChangePage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should rendering SizePerPageDropDown component successfully', () => {
|
|
||||||
const sizePerPageDropDown = wrapper.find(SizePerPageDropDown);
|
|
||||||
expect(sizePerPageDropDown.length).toBe(1);
|
|
||||||
|
|
||||||
expect(sizePerPageDropDown.prop('currSizePerPage')).toEqual(`${props.currSizePerPage}`);
|
|
||||||
expect(sizePerPageDropDown.prop('options')).toEqual(instance.calculateSizePerPageStatus());
|
|
||||||
expect(sizePerPageDropDown.prop('onSizePerPageChange')).toEqual(instance.handleChangeSizePerPage);
|
|
||||||
expect(sizePerPageDropDown.prop('onClick')).toEqual(instance.toggleDropDown);
|
|
||||||
expect(sizePerPageDropDown.prop('open')).toEqual(instance.state.dropdownOpen);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when props.sizePerPageList is empty array', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
const props = createMockProps({ sizePerPageList: [] });
|
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not rendering SizePerPageDropDown component', () => {
|
|
||||||
const sizePerPageDropDown = wrapper.find(SizePerPageDropDown);
|
|
||||||
expect(sizePerPageDropDown.length).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when props.hideSizePerPage is true', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
const props = createMockProps({ hideSizePerPage: true });
|
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not rendering SizePerPageDropDown component', () => {
|
|
||||||
const sizePerPageDropDown = wrapper.find(SizePerPageDropDown);
|
|
||||||
expect(sizePerPageDropDown.length).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when props.hidePageListOnlyOnePage is true', () => {
|
describe('when props.hidePageListOnlyOnePage is true', () => {
|
||||||
@@ -105,184 +62,78 @@ describe('Pagination', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should find react-bootstrap-table-pagination-list-hidden class when only one page', () => {
|
it('should find react-bootstrap-table-pagination-list-hidden class when only one page', () => {
|
||||||
expect(wrapper.find('.react-bootstrap-table-pagination-list-hidden').length).toBe(1);
|
expect(wrapper.dive().find('.react-bootstrap-table-pagination-list-hidden').length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('componentWillReceiveProps', () => {
|
describe('when props.pageListRenderer is defined', () => {
|
||||||
describe('when next props.currSizePerPage is diff than current one', () => {
|
let pageListRenderer;
|
||||||
const nextProps = createMockProps({ currSizePerPage: 20 });
|
beforeEach(() => {
|
||||||
|
pageListRenderer = jest.fn().mockReturnValue(null);
|
||||||
|
const props = createMockProps({ pageListRenderer });
|
||||||
|
wrapper = shallow(<Pagination { ...props } />);
|
||||||
|
wrapper.render();
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render PaginationList', () => {
|
||||||
|
expect(wrapper.dive().find(PaginationList)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call props.pageListRenderer correctly', () => {
|
||||||
|
expect(pageListRenderer).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when props.sizePerPageRenderer is defined', () => {
|
||||||
|
let sizePerPageRenderer;
|
||||||
|
beforeEach(() => {
|
||||||
|
sizePerPageRenderer = jest.fn().mockReturnValue(null);
|
||||||
|
const props = createMockProps({ sizePerPageRenderer });
|
||||||
|
wrapper = shallow(<Pagination { ...props } />);
|
||||||
|
wrapper.render();
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render SizePerPageDropDown', () => {
|
||||||
|
expect(wrapper.dive().find(SizePerPageDropDown)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call props.sizePerPageRenderer correctly', () => {
|
||||||
|
expect(sizePerPageRenderer).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when props.showTotal is true', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const props = createMockProps({ showTotal: true });
|
||||||
|
wrapper = shallow(<Pagination { ...props } />);
|
||||||
|
wrapper.render();
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render PaginationTotal correctly', () => {
|
||||||
|
expect(wrapper.dive().find(PaginationTotal)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if props.paginationTotalRenderer is defined', () => {
|
||||||
|
let paginationTotalRenderer;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = shallow(<Pagination { ...createMockProps() } />);
|
paginationTotalRenderer = jest.fn();
|
||||||
|
const props = createMockProps({ showTotal: true, paginationTotalRenderer });
|
||||||
|
wrapper = shallow(<Pagination { ...props } />);
|
||||||
|
wrapper.render();
|
||||||
instance = wrapper.instance();
|
instance = wrapper.instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setting correct state.totalPages', () => {
|
it('should not render PaginationTotal', () => {
|
||||||
instance.componentWillReceiveProps(nextProps);
|
expect(wrapper.dive().find(PaginationTotal)).toHaveLength(0);
|
||||||
expect(instance.state.totalPages).toEqual(
|
|
||||||
instance.calculateTotalPage(nextProps.currSizePerPage));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should setting correct state.lastPage', () => {
|
it('should call props.paginationTotalRenderer correctly', () => {
|
||||||
instance.componentWillReceiveProps(nextProps);
|
expect(paginationTotalRenderer).toHaveBeenCalledTimes(1);
|
||||||
const totalPages = instance.calculateTotalPage(nextProps.currSizePerPage);
|
|
||||||
expect(instance.state.lastPage).toEqual(
|
|
||||||
instance.calculateLastPage(totalPages));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when next props.dataSize is diff than current one', () => {
|
|
||||||
const nextProps = createMockProps({ dataSize: 33 });
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(<Pagination { ...createMockProps() } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should setting correct state.totalPages', () => {
|
|
||||||
instance.componentWillReceiveProps(nextProps);
|
|
||||||
expect(instance.state.totalPages).toEqual(
|
|
||||||
instance.calculateTotalPage(nextProps.currSizePerPage, nextProps.dataSize));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should setting correct state.lastPage', () => {
|
|
||||||
instance.componentWillReceiveProps(nextProps);
|
|
||||||
const totalPages = instance.calculateTotalPage(
|
|
||||||
nextProps.currSizePerPage, nextProps.dataSize);
|
|
||||||
expect(instance.state.lastPage).toEqual(
|
|
||||||
instance.calculateLastPage(totalPages));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toggleDropDown', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
const props = createMockProps();
|
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should setting state.dropdownOpen as true when it is false', () => {
|
|
||||||
instance.toggleDropDown();
|
|
||||||
expect(instance.state.dropdownOpen).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should setting state.dropdownOpen as false when it is true', () => {
|
|
||||||
instance.toggleDropDown();
|
|
||||||
instance.toggleDropDown();
|
|
||||||
expect(instance.state.dropdownOpen).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('closeDropDown', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
const props = createMockProps();
|
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should always setting state.dropdownOpen as false', () => {
|
|
||||||
instance.closeDropDown();
|
|
||||||
expect(instance.state.dropdownOpen).toBeFalsy();
|
|
||||||
instance.closeDropDown();
|
|
||||||
expect(instance.state.dropdownOpen).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handleChangeSizePerPage', () => {
|
|
||||||
const props = createMockProps();
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should always setting state.dropdownOpen to false', () => {
|
|
||||||
instance.handleChangeSizePerPage(10);
|
|
||||||
expect(instance.state.dropdownOpen).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when new sizePerPage is same as current one', () => {
|
|
||||||
it('should not calling props.onSizePerPageChange callback', () => {
|
|
||||||
instance.handleChangeSizePerPage(10);
|
|
||||||
expect(props.onSizePerPageChange.callCount).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when new sizePerPage is diff than current one', () => {
|
|
||||||
it('should not calling props.onSizePerPageChange callback', () => {
|
|
||||||
instance.handleChangeSizePerPage(30);
|
|
||||||
expect(props.onSizePerPageChange.callCount).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('and new current page is still in the new lagination list', () => {
|
|
||||||
it('should calling props.onSizePerPageChange with correct argument', () => {
|
|
||||||
expect(props.onSizePerPageChange.calledWith(30, props.currPage));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('and new current page is still in the new lagination list', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(<Pagination { ...createMockProps({ currPage: 10 }) } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calling props.onSizePerPageChange with correct argument', () => {
|
|
||||||
expect(props.onSizePerPageChange.calledWith(30, 4));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handleChangePage', () => {
|
|
||||||
const props = createMockProps();
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
props.currPage = 6;
|
|
||||||
wrapper = shallow(<Pagination { ...props } />);
|
|
||||||
instance = wrapper.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
props.onPageChange.reset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calling props.onPageChange correctly when new page is eq props.prePageText', () => {
|
|
||||||
instance.handleChangePage(props.prePageText);
|
|
||||||
expect(props.onPageChange.callCount).toBe(1);
|
|
||||||
expect(props.onPageChange.calledWith(5)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calling props.onPageChange correctly when new page is eq props.nextPageText', () => {
|
|
||||||
instance.handleChangePage(props.nextPageText);
|
|
||||||
expect(props.onPageChange.callCount).toBe(1);
|
|
||||||
expect(props.onPageChange.calledWith(7)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calling props.onPageChange correctly when new page is eq props.lastPageText', () => {
|
|
||||||
instance.handleChangePage(props.lastPageText);
|
|
||||||
expect(props.onPageChange.callCount).toBe(1);
|
|
||||||
expect(props.onPageChange.calledWith(10)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calling props.onPageChange correctly when new page is eq props.firstPageText', () => {
|
|
||||||
instance.handleChangePage(props.firstPageText);
|
|
||||||
expect(props.onPageChange.callCount).toBe(1);
|
|
||||||
expect(props.onPageChange.calledWith(props.pageStartIndex)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calling props.onPageChange correctly when new page is a numeric page', () => {
|
|
||||||
const newPage = '8';
|
|
||||||
instance.handleChangePage(newPage);
|
|
||||||
expect(props.onPageChange.callCount).toBe(1);
|
|
||||||
expect(props.onPageChange.calledWith(parseInt(newPage, 10))).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not calling props.onPageChange correctly when page is not changed', () => {
|
|
||||||
const newPage = props.currPage;
|
|
||||||
instance.handleChangePage(newPage);
|
|
||||||
expect(props.onPageChange.callCount).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import sizePerPageDropdownAdapter from '../src/size-per-page-dropdown-adapter';
|
||||||
|
|
||||||
|
|
||||||
|
const MockComponent = () => null;
|
||||||
|
|
||||||
|
const SizePerPageDropdownAdapter = sizePerPageDropdownAdapter(MockComponent);
|
||||||
|
describe('sizePerPageDropdownAdapter', () => {
|
||||||
|
let wrapper;
|
||||||
|
let instance;
|
||||||
|
|
||||||
|
const createMockProps = props => ({
|
||||||
|
dataSize: 100,
|
||||||
|
sizePerPageList: [10, 20, 30, 50],
|
||||||
|
currPage: 1,
|
||||||
|
currSizePerPage: 10,
|
||||||
|
alwaysShowAllBtns: false,
|
||||||
|
onSizePerPageChange: jest.fn(),
|
||||||
|
hidePageListOnlyOnePage: false,
|
||||||
|
hideSizePerPage: false,
|
||||||
|
optionRenderer: jest.fn(),
|
||||||
|
sizePerPageOptionRenderer: jest.fn(),
|
||||||
|
...props
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('render', () => {
|
||||||
|
const props = createMockProps();
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const mockComponent = wrapper.find(MockComponent);
|
||||||
|
expect(mockComponent).toHaveLength(1);
|
||||||
|
|
||||||
|
expect(mockComponent.props().currSizePerPage).toEqual(`${props.currSizePerPage}`);
|
||||||
|
expect(mockComponent.props().options).toBeDefined();
|
||||||
|
expect(mockComponent.props().optionRenderer).toBeDefined();
|
||||||
|
expect(mockComponent.props().onSizePerPageChange).toEqual(instance.handleChangeSizePerPage);
|
||||||
|
expect(mockComponent.props().onClick).toEqual(instance.toggleDropDown);
|
||||||
|
expect(mockComponent.props().onBlur).toEqual(instance.closeDropDown);
|
||||||
|
expect(mockComponent.props().open).toEqual(instance.state.dropdownOpen);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when props.sizePerPageList is empty array', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const props = createMockProps({ sizePerPageList: [] });
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render component', () => {
|
||||||
|
const sizePerPageDropDown = wrapper.find(MockComponent);
|
||||||
|
expect(sizePerPageDropDown.length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when props.hideSizePerPage is true', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const props = createMockProps({ hideSizePerPage: true });
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not rendering SizePerPageDropDown component', () => {
|
||||||
|
const sizePerPageDropDown = wrapper.find(MockComponent);
|
||||||
|
expect(sizePerPageDropDown.length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('toggleDropDown', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const props = createMockProps();
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set state.dropdownOpen as true when it is false', () => {
|
||||||
|
instance.toggleDropDown();
|
||||||
|
expect(instance.state.dropdownOpen).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set state.dropdownOpen as false when it is true', () => {
|
||||||
|
instance.toggleDropDown();
|
||||||
|
instance.toggleDropDown();
|
||||||
|
expect(instance.state.dropdownOpen).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('closeDropDown', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const props = createMockProps();
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always set state.dropdownOpen as false', () => {
|
||||||
|
instance.closeDropDown();
|
||||||
|
expect(instance.state.dropdownOpen).toBeFalsy();
|
||||||
|
instance.closeDropDown();
|
||||||
|
expect(instance.state.dropdownOpen).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handleChangeSizePerPage', () => {
|
||||||
|
let props;
|
||||||
|
const sizePerPage = 25;
|
||||||
|
beforeEach(() => {
|
||||||
|
props = createMockProps();
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
instance.handleChangeSizePerPage(sizePerPage);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call props.onSizePerPageChange correctly', () => {
|
||||||
|
expect(props.onSizePerPageChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(props.onSizePerPageChange).toHaveBeenCalledWith(sizePerPage);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always set state.dropdownOpen as false', () => {
|
||||||
|
expect(instance.state.dropdownOpen).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when props.sizePerPageRenderer is defined', () => {
|
||||||
|
const sizePerPageRenderer = jest.fn().mockReturnValue(null);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sizePerPageRenderer.mockClear();
|
||||||
|
const props = createMockProps({ sizePerPageRenderer });
|
||||||
|
wrapper = shallow(<SizePerPageDropdownAdapter { ...props } />);
|
||||||
|
instance = wrapper.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render default component', () => {
|
||||||
|
expect(wrapper.find(MockComponent)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call props.sizePerPageRenderer correctly', () => {
|
||||||
|
expect(sizePerPageRenderer).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -178,4 +178,23 @@ describe('SizePerPageDropDown', () => {
|
|||||||
expect(wrapper.hasClass(className)).toBeTruthy();
|
expect(wrapper.hasClass(className)).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when optionRenderer prop is defined', () => {
|
||||||
|
const optionRenderer = jest.fn();
|
||||||
|
beforeEach(() => {
|
||||||
|
optionRenderer.mockReset();
|
||||||
|
wrapper = shallowWithContext(
|
||||||
|
<SizePerPageDropDown { ...props } optionRenderer={ optionRenderer } />,
|
||||||
|
{ bootstrap4: false }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render SizePerPageOption', () => {
|
||||||
|
expect(wrapper.find(SizePerPageOption)).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call optionRenderer prop correctly', () => {
|
||||||
|
expect(optionRenderer).toHaveBeenCalledTimes(props.options.length);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user