Compare commits

..

180 Commits

Author SHA1 Message Date
AllenFang
6070d150a9 Publish
- react-bootstrap-table2-example@1.0.18
 - react-bootstrap-table2-paginator@2.0.3
 - react-bootstrap-table2-toolkit@1.3.0
 - react-bootstrap-table-next@2.2.0
2019-02-20 23:08:26 +08:00
Allen
dab6f1b206 Merge pull request #810 from react-bootstrap-table/develop
20190220 release
2019-02-20 23:05:03 +08:00
Allen
2a497194e7 Merge pull request #801 from react-bootstrap-table/enhance/795
Implement PaginationTotalStandalone
2019-02-17 17:41:57 +08:00
AllenFang
f5f17897fd add story for PaginationTotalStandalone 2019-02-17 17:29:56 +08:00
AllenFang
2932b8a1b8 fix #795 2019-02-17 17:29:56 +08:00
AllenFang
93103e5ca0 exclude examples from coverage 2019-02-17 17:17:56 +08:00
AllenFang
a7c2a49182 fix #793 2019-02-17 15:25:32 +08:00
Allen
cd27ff98ff Merge pull request #800 from react-bootstrap-table/feat/723
Implement Column Toggle(723)
2019-02-17 15:24:17 +08:00
AllenFang
4d815894e6 add stories for #723 2019-02-17 14:55:44 +08:00
AllenFang
d9ff201373 fix #723 2019-02-17 14:55:17 +08:00
AllenFang
8e142de332 Publish
- react-bootstrap-table2-example@1.0.17
 - react-bootstrap-table2-filter@1.1.4
 - react-bootstrap-table2-toolkit@1.2.2
 - react-bootstrap-table-next@2.1.2
2019-02-16 17:11:10 +08:00
Allen
322605f14e Merge pull request #798 from react-bootstrap-table/develop
20190216 release
2019-02-16 17:09:40 +08:00
Allen
3156e01dd6 fix #788 (#797) 2019-02-16 16:26:26 +08:00
Allen
052284a163 fix #791 (#796) 2019-02-16 16:18:33 +08:00
AllenFang
3cd8efffb9 Publish
- react-bootstrap-table2-example@1.0.16
 - react-bootstrap-table2-filter@1.1.3
 - react-bootstrap-table2-paginator@2.0.2
 - react-bootstrap-table2-toolkit@1.2.1
 - react-bootstrap-table-next@2.1.1
2019-02-09 21:07:26 +08:00
Allen
447d69cae5 Merge pull request #790 from react-bootstrap-table/develop
20190209 release
2019-02-09 21:04:28 +08:00
AllenFang
cacc28e1bc fix test cases 2019-02-09 20:28:28 +08:00
AllenFang
d7f84a9da5 fix remote filter/search broken when pagination enabled 2019-02-09 18:01:53 +08:00
AllenFang
63c2630f46 fix same issue #778, but for search 2019-02-07 15:44:15 +08:00
AllenFang
903dd2e5c8 rename listenerForPagination -> dataChangeListener 2019-02-07 15:34:03 +08:00
AllenFang
964faa53e3 fix wrong storyb code 2019-02-07 13:56:42 +08:00
AllenFang
8fb5364cc2 add story for #445 2019-02-06 22:56:53 +08:00
AllenFang
8b89b3de0e fix #445 2019-02-06 22:56:31 +08:00
AllenFang
4506a3dea2 add story for #778 2019-02-06 18:06:08 +08:00
AllenFang
ecea3efdaa fix #778 2019-02-06 18:05:53 +08:00
AllenFang
8bef7eb348 fix #672 2019-02-06 15:15:26 +08:00
AllenFang
408a004f58 Publish
- react-bootstrap-table2-example@1.0.15
 - react-bootstrap-table2-filter@1.1.2
 - react-bootstrap-table2-toolkit@1.2.0
 - react-bootstrap-table-next@2.1.0
2019-01-20 22:50:11 +08:00
Allen
bf46dfa026 Merge pull request #766 from react-bootstrap-table/develop
20190120 release
2019-01-20 22:47:34 +08:00
AllenFang
f1b39e3dd6 patch docs for clear search button 2019-01-20 17:20:41 +08:00
AllenFang
029cd3ab6f add story for #751 2019-01-20 17:16:44 +08:00
AllenFang
1c68892a7b fix #751 2019-01-20 17:15:54 +08:00
AllenFang
1bf3fa50db patch docs for table footer 2019-01-20 15:40:51 +08:00
AllenFang
9988e790c1 Merge branch 'osiux-table-footer' into develop 2019-01-20 14:39:26 +08:00
AllenFang
bb071c98f9 fix typo 2019-01-20 14:19:12 +08:00
AllenFang
9c5d8aac62 Merge branch 'table-footer' of https://github.com/osiux/react-bootstrap-table2 into osiux-table-footer 2019-01-20 14:11:13 +08:00
AllenFang
7c79b64985 enhance clear filter story 2019-01-20 14:07:05 +08:00
Martins Linde
16f89989f0 Allow null date when clearing date filter with getFilter function (#759)
* fix date filter's getFilter function to accept empty value for clearing

* syntax improvements from ESlint
2019-01-20 14:03:24 +08:00
Eduardo Reveles
58cfdacfd1 fix error 2019-01-16 00:11:27 -06:00
Eduardo Reveles
78d5164056 add more examples to storybook 2019-01-15 21:40:01 -06:00
Eduardo Reveles
bd2ce5abf0 Add table footer 2019-01-15 21:40:01 -06:00
AllenFang
416fcf08d4 Publish
- react-bootstrap-table2-example@1.0.14
 - react-bootstrap-table2-filter@1.1.1
 - react-bootstrap-table2-paginator@2.0.1
 - react-bootstrap-table2-toolkit@1.1.2
 - react-bootstrap-table-next@2.0.1
2019-01-06 17:06:20 +08:00
Allen
0c650c0682 Merge pull request #747 from react-bootstrap-table/develop
20190106 release
2019-01-06 17:03:34 +08:00
Allen
7d30804da9 fix #636 (#746) 2019-01-06 16:25:02 +08:00
Allen
782c630e58 fix #734, fix #620 (#745) 2019-01-06 14:47:22 +08:00
Allen
22cc79961f fix #715 (#743) 2019-01-05 20:45:18 +08:00
Allen
a83b3d0d78 fix #729 (#742) 2019-01-05 17:00:52 +08:00
Allen
340ddb8722 fix #719 (#741) 2019-01-05 16:09:12 +08:00
AllenFang
32e455e65f add remote standalone pagination story 2019-01-05 14:37:07 +08:00
AllenFang
6c0fc2748c Publish
- react-bootstrap-table2-example@1.0.13
 - react-bootstrap-table2-paginator@2.0.0
 - react-bootstrap-table-next@2.0.0
2018-12-25 23:38:34 +08:00
Allen
973ece8b39 Merge pull request #727 from react-bootstrap-table/develop
20181225 release
2018-12-25 23:37:05 +08:00
Allen
0a94f3ce39 Merge pull request #681 from react-bootstrap-table/refactoring/pagination
Easy to customize pagination
2018-12-24 11:18:44 +08:00
AllenFang
0ca8e54ce2 Publish
- react-bootstrap-table-next@1.4.4
2018-12-23 20:30:41 +08:00
Allen
69d534e26c Merge pull request #726 from react-bootstrap-table/develop
20181223 release
2018-12-23 20:29:20 +08:00
AllenFang
c2a30cb716 fix #725 2018-12-23 19:44:26 +08:00
AllenFang
83dc888d17 patch docs for new pagination 2018-12-22 15:56:14 +08:00
AllenFang
41da9afbcb paginationBaseProps -> paginationTableProps 2018-12-22 15:55:02 +08:00
AllenFang
91816fcc01 add stories for custom pagination 2018-12-22 14:03:02 +08:00
AllenFang
620309115f extract useless function from pagination ro paginationHandler 2018-12-22 14:03:02 +08:00
AllenFang
297f3e0c4f implement SizePerPageDropdownStandalone 2018-12-22 14:03:02 +08:00
AllenFang
d42a10bbae implement PaginationListStandalone 2018-12-22 14:03:02 +08:00
AllenFang
5c52412542 fix remote pagination broken 2018-12-22 14:03:02 +08:00
AllenFang
a5f74cecfe implement sizePerPageRenderer 2018-12-22 14:03:02 +08:00
AllenFang
a30a8fd96b implement sizePerPageOptionRenderer 2018-12-22 14:03:02 +08:00
AllenFang
424dbea270 implement pageListRenderer 2018-12-22 14:03:02 +08:00
AllenFang
b261c33e37 implement pageButtonRenderer 2018-12-22 14:03:02 +08:00
AllenFang
7dbdc1943b patch pagination context test suites 2018-12-22 14:03:02 +08:00
AllenFang
d4be1675db refactoring pagination context 2018-12-22 14:03:02 +08:00
AllenFang
d3161f02eb Publish
- react-bootstrap-table2-example@1.0.12
 - react-bootstrap-table-next@1.4.3
2018-12-21 16:51:04 +08:00
Allen
28ba6d5677 Merge pull request #721 from react-bootstrap-table/develop
20181221 release
2018-12-21 16:49:35 +08:00
AllenFang
4ddbfd4972 fix #711 2018-12-21 16:23:38 +08:00
AllenFang
d84dc46ff1 Merge branch 'vinzentt-fix-nonExpandable-indicator-and-behaviour' into develop 2018-12-20 23:52:42 +08:00
AllenFang
e0163625d4 add expandable for expandColumnRenderer 2018-12-20 23:47:30 +08:00
AllenFang
24ab58a464 row expandable already calculated from row expand consumer, just use it instead do the logic again 2018-12-20 23:45:20 +08:00
Allen
6e19368733 Merge branch 'develop' into fix-nonExpandable-indicator-and-behaviour 2018-12-20 23:27:48 +08:00
AllenFang
bc4697bf95 fix #701 2018-12-20 23:20:12 +08:00
AllenFang
9d2a6a1b23 Publish
- react-bootstrap-table2-example@1.0.11
 - react-bootstrap-table-next@1.4.2
2018-12-05 23:31:35 +08:00
Allen
bb752fcec8 Merge pull request #699 from react-bootstrap-table/develop
20181205 release
2018-12-05 23:30:19 +08:00
Vincent Degroote
aedd1f5942 Add expandColumn in storybook example for nonExpandable rows 2018-12-05 11:37:32 +01:00
Vincent Degroote
5a5f10f609 fix tests when nonExpndable is not given 2018-12-05 11:23:38 +01:00
Vincent Degroote
e041a3d736 revert not needed changes 2018-12-05 10:55:04 +01:00
Vincent Degroote
f175fd4186 Hide expand indicator if row is not expandable and prevent it from being expanded 2018-12-05 10:50:52 +01:00
AllenFang
5a6b7e122d fix #680 2018-12-02 17:45:42 +08:00
AllenFang
a7ae524c49 fix #675 2018-12-02 17:29:25 +08:00
AllenFang
a23599f52f fix #669 2018-12-02 17:04:32 +08:00
EricH
c50853b16d Fix typo in doc example code (#691) 2018-12-02 15:48:52 +08:00
NickChen
3f74542c98 Merge pull request #670 from react-bootstrap-table/enhancement/remove-unnecessary-props-bootstrap4
LGTM
2018-11-18 18:04:24 +08:00
Chun-MingChen
47aa41b8fa Remove unnecessary props 'bootstrap4' 2018-11-18 17:55:27 +08:00
AllenFang
67ed2e6c80 Publish
- react-bootstrap-table2-editor@1.2.2
 - react-bootstrap-table2-example@1.0.10
 - react-bootstrap-table2-filter@1.1.0
 - react-bootstrap-table2-paginator@1.0.4
 - react-bootstrap-table-next@1.4.1
2018-11-10 17:19:43 +08:00
Allen
794a97956d Merge pull request #661 from react-bootstrap-table/develop
20181110 release
2018-11-10 17:18:11 +08:00
AllenFang
78ca01bb1a fix #582 2018-11-10 16:58:02 +08:00
Yassien
b79dbc80f6 Condensed now takes bootstrap4 into consideration (#653) 2018-11-10 15:55:54 +08:00
AllenFang
3f21a67620 Merge branch 'develop' of https://github.com/react-bootstrap-table/react-bootstrap-table2 into develop 2018-11-10 15:54:10 +08:00
AllenFang
9e3ae385ce Merge branch 'jehartzog-fix-select-filter-typo' into develop 2018-11-10 15:53:43 +08:00
AllenFang
c6ea19fe8a enhance for #649 2018-11-10 15:53:20 +08:00
AllenFang
a5b42dca92 Merge branch 'fix-select-filter-typo' of https://github.com/jehartzog/react-bootstrap-table2 into jehartzog-fix-select-filter-typo 2018-11-10 15:45:08 +08:00
Joshua
28f3c33db3 Update README.md (#658)
* Update README.md

* Address review comment

Co-Authored-By: konekoya <tank158r5155@yahoo.com.tw>

* Use being instead of is

Co-Authored-By: konekoya <tank158r5155@yahoo.com.tw>
2018-11-10 15:43:23 +08:00
Allen
2530a70c00 fix #654 #611 (#660) 2018-11-10 15:42:59 +08:00
AllenFang
569dd61463 fix #655 2018-11-10 13:55:46 +08:00
EricH
68264b45ce fix #641 typo 2018-11-05 07:09:39 -07:00
AllenFang
e251068657 Publish
- react-bootstrap-table2-example@1.0.9
 - react-bootstrap-table2-filter@1.0.2
 - react-bootstrap-table-next@1.4.0
2018-11-05 00:11:59 +08:00
Allen
e4fbb284b4 Merge pull request #647 from react-bootstrap-table/develop
20181104 release
2018-11-05 00:04:22 +08:00
Allen
a6afc9d9a8 Merge pull request #646 from react-bootstrap-table/enhance/641
Enhance/641
2018-11-04 16:44:11 +08:00
AllenFang
a0ba41c103 patch docs for #641 2018-11-04 16:32:13 +08:00
AllenFang
4a16cb314d add story for #641 2018-11-04 16:24:48 +08:00
AllenFang
98a04a5710 fix #641 2018-11-04 16:24:34 +08:00
Allen
c22a2a1d71 Merge pull request #644 from react-bootstrap-table/enhance/297
Enhance/297
2018-11-03 17:58:22 +08:00
AllenFang
9bc25c9d3e patch docs for selection control 2018-11-03 16:45:05 +08:00
AllenFang
4554db02d2 add story for advance selection contrl 2018-11-03 16:37:51 +08:00
AllenFang
b7fac973d2 fix #297 2018-11-03 16:37:02 +08:00
AllenFang
6925358631 Publish
- react-bootstrap-table2-editor@1.2.1
 - react-bootstrap-table2-example@1.0.8
 - react-bootstrap-table-next@1.3.1
2018-10-30 00:01:35 +08:00
Allen
27c3cdab29 Merge pull request #635 from react-bootstrap-table/develop
20181028 release
2018-10-29 23:59:30 +08:00
AllenFang
bc0c048735 try to fix #620 2018-10-28 17:35:16 +08:00
Allen
a4c1090a0f Merge pull request #634 from react-bootstrap-table/feat/583
Feat/583
2018-10-28 17:16:51 +08:00
AllenFang
5fac4540a1 patch test for #583 2018-10-28 16:59:44 +08:00
AllenFang
f7a06401ae patch docs and story for #583 2018-10-28 16:51:36 +08:00
AllenFang
858ad9543b fix #583 2018-10-28 16:51:13 +08:00
AllenFang
abf618ce6d Merge branch 'develop' of https://github.com/react-bootstrap-table/react-bootstrap-table2 into develop 2018-10-28 16:04:41 +08:00
AllenFang
ea6cb78302 patch docs for #604 2018-10-28 16:04:25 +08:00
Allen
bacbfdbbf0 Merge pull request #633 from react-bootstrap-table/feat/604
Feat/604
2018-10-28 16:01:14 +08:00
AllenFang
465212ff35 patch story 2018-10-28 15:51:45 +08:00
AllenFang
2a58f99a97 add story for #604 2018-10-28 15:50:56 +08:00
AllenFang
7bda61f5be fix #604 2018-10-28 15:50:43 +08:00
Allen
7220b2d073 Merge pull request #632 from react-bootstrap-table/enhance/621
Enhance/621
2018-10-28 14:49:09 +08:00
AllenFang
f7a1c91904 patch story for #621 2018-10-28 14:32:39 +08:00
AllenFang
ea827bfeb5 patch docs for #621 2018-10-28 14:32:28 +08:00
AllenFang
f1f4bd784d fix #621 2018-10-28 14:32:11 +08:00
Ryan Waskiewicz
569c22ba49 Update development.md with git clone directory (#605)
* Update development.md

- Update directory name that's created after cloning the project
- Remove lerna bootstrap step (appears to be run as a postinstall step in npm scripts)

* Update development.md
2018-10-21 14:45:25 +08:00
AllenFang
b1e5c0cb20 Publish
- react-bootstrap-table2-editor@1.2.0
 - react-bootstrap-table2-example@1.0.7
 - react-bootstrap-table2-filter@1.0.1
 - react-bootstrap-table-next@1.3.0
2018-10-14 23:49:57 +08:00
Allen
7ee38a647f Merge pull request #608 from react-bootstrap-table/develop
20181014 release
2018-10-14 23:45:50 +08:00
AllenFang
01ec19344d patch docs and proptype for selectRow.clickToExpand 2018-10-14 16:04:04 +08:00
AllenFang
19be67c914 fix #599 2018-10-14 15:07:30 +08:00
Allen
ae4d38cae6 Merge pull request #607 from react-bootstrap-table/enhance/598
Enhance/598
2018-10-14 14:49:43 +08:00
AllenFang
81a6428a03 patch docs for #598 2018-10-14 14:44:19 +08:00
AllenFang
166affc4c1 add story for #598 2018-10-14 14:44:19 +08:00
AllenFang
d0fb46e39f patch test for #598 2018-10-14 14:41:14 +08:00
AllenFang
828844a1e9 fix #598 2018-10-14 14:40:53 +08:00
Allen
774293b76d Merge pull request #497 from react-bootstrap-table/refactor/selection-consumer
Row Refactoring with Consumer and perf improvement
2018-10-14 13:38:28 +08:00
Benjamin Cavy
e77cbdb2df Add MULTISELECT filter type in filter doc (#606) 2018-10-14 13:32:36 +08:00
AllenFang
ef2f828572 patch docs and story for #546 2018-10-11 00:08:31 +08:00
AllenFang
15731932cf fix #546 2018-10-11 00:08:13 +08:00
AllenFang
dd54294382 refine large table example 2018-10-10 23:54:11 +08:00
AllenFang
185c184f01 upgrade react 2018-10-09 00:18:17 +08:00
AllenFang
d45345ed10 binder -> consumer 2018-10-09 00:18:17 +08:00
AllenFang
dda8460017 implement selectRow.clickToExpand 2018-10-09 00:18:17 +08:00
AllenFang
6735536fd8 refactoring cell edit consumer 2018-10-09 00:18:17 +08:00
AllenFang
95623bbb5f fix selection header checkbox will be checked when table data is empty 2018-10-09 00:18:17 +08:00
AllenFang
9567c7829d refactoring shouldComponentUpdate for aggreate and simple row for cell editing 2018-10-09 00:18:17 +08:00
AllenFang
8499991c41 fix cell edit broken 2018-10-09 00:18:17 +08:00
AllenFang
1e76ca9bdb fix row-pure-content will not update in some case 2018-10-09 00:18:17 +08:00
AllenFang
fa13550d8c patch test for row selection consumer refactoring 2018-10-09 00:18:17 +08:00
AllenFang
709d59ce62 patch tests for row refactoring 2018-10-09 00:18:16 +08:00
AllenFang
66329ecdbf implement selection consumers 2018-10-09 00:18:16 +08:00
AllenFang
ee6cec5a2d refactoring row level components 2018-10-09 00:18:16 +08:00
AllenFang
52fc84899b fixed wrong conflict fixs for #514 2018-10-09 00:18:16 +08:00
AllenFang
8c10867b8c fix cell level performace, remain select all 2018-10-09 00:18:16 +08:00
AllenFang
640ada7659 patch tests for refactoring cell edit with consumer 2018-10-09 00:18:16 +08:00
AllenFang
73a5c34535 add story for dbclick to edit with row selection 2018-10-09 00:18:16 +08:00
AllenFang
2879cf891e refactoring cell edit consumer 2018-10-09 00:18:16 +08:00
AllenFang
994ed2e395 no more expand row props resolver 2018-10-09 00:18:16 +08:00
AllenFang
4b790e4bec patch test for refining expand row consumer 2018-10-09 00:18:16 +08:00
AllenFang
21e7c3a53a refine expand row consumer 2018-10-09 00:18:16 +08:00
AllenFang
6fce0d7066 add story for combine selection and expansion 2018-10-09 00:18:16 +08:00
AllenFang
154f1c91c3 upgrade enzyme for new context API 2018-10-09 00:18:16 +08:00
AllenFang
02d78e5104 patch tests for refactoring row component with selection 2018-10-09 00:18:16 +08:00
AllenFang
41cc6b01af patch row event example 2018-10-09 00:18:16 +08:00
AllenFang
bd410e7303 refine selection consumer 2018-10-09 00:18:16 +08:00
Allen
eced3eef1f Merge pull request #597 from react-bootstrap-table/feature/introduce-logo-to-storybook
Feature/introduce logo to storybook
2018-10-09 00:16:48 +08:00
Chun-MingChen
ca5a41a8b3 Change primary of github avatar to main color of logo 2018-10-08 00:19:29 +08:00
Chun-MingChen
7a31729ebb Introduce logo to <Welcome /> 2018-10-08 00:19:29 +08:00
Chun-MingChen
3a8faf8170 Add favicon 2018-10-07 23:57:16 +08:00
AllenFang
532581bb6e Publish
- react-bootstrap-table2-example@1.0.6
 - react-bootstrap-table2-paginator@1.0.3
 - react-bootstrap-table2-toolkit@1.1.1
 - react-bootstrap-table-next@1.2.1
2018-10-07 23:33:25 +08:00
Allen
c228b229d2 Merge pull request #595 from react-bootstrap-table/develop
20181007 release
2018-10-07 23:31:56 +08:00
AllenFang
10adbf472c fix no-console 2018-10-07 16:24:15 +08:00
Allen
a6e2f0f8f8 fix #589 (#594) 2018-10-06 23:42:55 +08:00
Allen
f1d93853ec Merge pull request #593 from react-bootstrap-table/feat/587
Feat/587
2018-10-06 22:46:43 +08:00
AllenFang
bb7243c5db patch docs for column.sortCaret 2018-10-06 18:15:21 +08:00
AllenFang
3ea816b2e6 add story for #587 2018-10-06 18:15:21 +08:00
AllenFang
b268c4e0cd fix #587 2018-10-06 18:15:21 +08:00
Allen
8b8f336878 fix #585 (#592) 2018-10-06 17:29:24 +08:00
Allen
8517248aee fix #588 (#591) 2018-10-06 16:29:08 +08:00
187 changed files with 11933 additions and 4294 deletions

View File

@@ -1,43 +1,52 @@
# react-bootstrap-table2 # react-bootstrap-table2
[![Build Status](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2.svg?branch=master)](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2) [![Build Status](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2.svg?branch=master)](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 kernel 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)**

View File

@@ -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.

View File

@@ -62,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.

View File

@@ -13,6 +13,7 @@ Available properties in a column object:
* [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)
@@ -29,6 +30,14 @@ Available properties in a column object:
* [headerAttrs](#headerAttrs) * [headerAttrs](#headerAttrs)
* [headerSortingClasses](#headerSortingClasses) * [headerSortingClasses](#headerSortingClasses)
* [headerSortingStyle](#headerSortingStyle) * [headerSortingStyle](#headerSortingStyle)
* [footer](#footer)
* [footerFormatter](#footerFormatter)
* [footerClasses](#footerClasses)
* [footerStyle](#footerStyle)
* [footerTitle](#footerTitle)
* [footerEvents](#footerEvents)
* [footerAlign](#footerAlign)
* [footerAttrs](#footerAttrs)
* [editable](#editable) * [editable](#editable)
* [validator](#validator) * [validator](#validator)
* [editCellStyle](#editCellStyle) * [editCellStyle](#editCellStyle)
@@ -154,6 +163,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:
@@ -287,7 +310,7 @@ A new `Object` will be the result of element headerStyle.
A new `String` will be the result of element title. A new `String` will be the result of element title.
## <a name='headerTitle'>column.headerTitle - [Bool | Function]</a> ## <a name='headerTitle'>column.headerTitle - [Bool | Function]</a>
`headerTitle` is only for the title on header column, default is disable. The usage almost same as [`column.title`](#title), Configure the title on header column, default is disable. The usage almost same as [`column.title`](#title),
```js ```js
{ {
@@ -364,17 +387,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.
@@ -493,6 +526,162 @@ const sortingHeaderStyle = {
}; };
``` ```
### <a name='footer'>footer - [String | Function]</a>
Give a string to render the string value on the footer column.
```js
const columns = [{
dataField: 'id',
text: 'Product ID',
footerAlign: 'center',
footer: 'Footer 1'
}, .....];
```
This prop also accept a function:
```js
{
dataField: 'price',
text: 'Product Price',
footer: column => column.reduce((acc, item) => acc + item, 0)
}
```
## <a name='footerFormatter'>column.footerFormatter - [Function]</a>
`footerFormatter` allow you to customize the table footer column and only accept a callback function which take two arguments and a JSX/String are expected for return.
* `column`
* `columnIndex`
## <a name='footerClasses'>column.footerClasses - [String | Function]</a>
It's similar to [`column.classes`](#classes), `footerClasses` is available to have customized class on table footer column:
```js
{
// omit...
footerClasses: 'id-custom-cell'
}
```
Furthermore, it also accept a callback function which takes 2 arguments and a `String` is expect to return:
```js
{
footerClasses: function callback(column, colIndex) { ... }
}
```
**Parameters**
* `column`: The value of current column.
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
## <a name='footerStyle'>column.footerStyle - [Object | Function]</a>
Customized the inline-style on table footer column:
```js
{
// omit...
footerStyle: { backgroundColor: 'green' }
}
```
Moreover, it also accept a callback function which takes **2** arguments and an `Object` is expect to return:
```js
{
footerStyle: function callback(column, colIndex) { ... }
}
```
**Parameters**
* `column`: The value of current column.
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
## <a name='footerTitle'>column.footerTitle - [Bool | Function]</a>
Configure the title on footer column, default is disable. The usage is almost same as [`column.title`](#title),
```js
{
// omit...
footerTitle: true
}
```
It's also available to custom via a callback function:
```js
{
footerTitle: function callback(column, colIndex) { ... }
}
```
**Parameters**
* `column`: The value of current column.
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
## <a name='footerEvents'>column.footerEvents - [Object]</a>
`footerEvents` same as [`column.events`](#events) but it is for footer column:
```js
{
// omit...
footerEvents: {
onClick: e => { ... }
}
}
```
## <a name='footerAlign'>column.footerAlign - [String | Function]</a>
It's almost same as [`column.align`](#align), but it's for the [CSS text-align](https://www.w3schools.com/cssref/pr_text_text-align.asp) on footer column.
```js
{
// omit...
footerAlign: 'center'
}
```
Also, you can custom the align by a callback function:
```js
{
// omit...
footerAlign: (column, colIndex) => {
// column is an object and perform itself
// return custom title here
}
}
```
**Parameters**
* `column`: The value of current column.
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
## <a name='footerAttrs'>column.footerAttrs - [Object | Function]</a>
`footerAttrs` is similar to [`column.attrs`](#attrs) but it works for footer column.
```js
{
// omit...
footerAttrs: {
title: 'bar',
'data-test': 'foo'
}
}
```
Additionally, customize the header attributes by a **2** arguments callback function:
```js
{
// omit...
footerAttrs: (column, colIndex) => ({
// return customized HTML attribute here
})
}
```
**Parameters**
* `column`: The value of current column.
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
## <a name='editable'>column.editable - [Bool | Function]</a> ## <a name='editable'>column.editable - [Bool | Function]</a>
`column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`. `column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`.
@@ -528,6 +717,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:

View File

@@ -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
``` ```
@@ -25,4 +25,4 @@ $ npm run storybook
$ npm test $ npm test
$ npm run test:watch # for watch mode $ npm run test:watch # for watch mode
$ npm run test:coverage # generate coverage report $ npm run test:coverage # generate coverage report
``` ```

View File

@@ -23,7 +23,7 @@ Currently, **I still can't implement all the mainly features in legacy `react-bo
* [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay) * [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay)
* Overlay/Loading Addons * Overlay/Loading Addons
* [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit) * [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit)
* Table Toolkits, like search, csv etc. * Table Toolkits, like search, csv, column toggle etc.
This can help your application with less bundled size and also help `react-bootstrap-table2` have clean design to avoid handling to much logic in kernel module(SRP). Hence, which means you probably need to install above addons when you need specific features. This can help your application with less bundled size and also help `react-bootstrap-table2` have clean design to avoid handling to much logic in kernel module(SRP). Hence, which means you probably need to install above addons when you need specific features.
@@ -113,14 +113,12 @@ 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
he 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. he 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.
- [x] Custom search component and position - [x] Custom search component and position
- [x] Custom search value - [x] Custom search value
- [ ] Clear search - [x] Clear search
- [ ] Multiple search - [ ] Multiple search
- [ ] Strict search - [ ] Strict search

View File

@@ -14,6 +14,8 @@
* [onExpandAll](#onExpandAll) * [onExpandAll](#onExpandAll)
* [showExpandColumn](#showExpandColumn) * [showExpandColumn](#showExpandColumn)
* [onlyOneExpanding](#onlyOneExpanding) * [onlyOneExpanding](#onlyOneExpanding)
* [expandByColumnOnly](#expandByColumnOnly)
* [expandColumnPosition](#expandColumnPosition)
* [expandColumnRenderer](#expandColumnRenderer) * [expandColumnRenderer](#expandColumnRenderer)
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer) * [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
@@ -91,13 +93,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 }) => (
// .... // ....
) )
}; };
@@ -138,3 +143,25 @@ const expandRow = {
onlyOneExpanding: true 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
};
```
### <a name='expandColumnPosition'>expandRow.expandColumnPosition - [String]</a>
Default is `left`. You can give this as `right` for rendering expand column in the right side.
```js
const expandRow = {
renderer: (row) => ...,
showExpandColumn: true,
expandColumnPosition: 'right'
};
```

View File

@@ -12,6 +12,7 @@
* [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)
@@ -148,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
@@ -165,7 +176,7 @@ Provide a callback function which allow you to custom the checkbox/radio box. Th
```js ```js
const selectRow = { const selectRow = {
mode: 'checkbox', mode: 'checkbox',
selectionRenderer: ({ mode, checked, disabled }) => ( selectionRenderer: ({ mode, checked, disabled, rowIndex }) => (
// .... // ....
) )
}; };
@@ -200,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`

View File

@@ -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 = () => {

View File

@@ -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,14 +82,15 @@
"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": {
"collectCoverageFrom": [ "collectCoverageFrom": [
"packages/*/src/**/*.js", "packages/*/src/**/*.js",
"packages/*/index.js" "packages/*/index.js",
"!packages/react-bootstrap-table2-example/**/*.js"
], ],
"roots": [ "roots": [
"<rootDir>/packages" "<rootDir>/packages"

View File

@@ -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

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-editor", "name": "react-bootstrap-table2-editor",
"version": "1.1.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": {

View File

@@ -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,
@@ -32,7 +31,7 @@ export default (
constructor(props) { constructor(props) {
super(props); super(props);
EditingCell = props.cellEdit.editingCellFactory(_, props.cellEdit.options.onStartEdit); 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);
@@ -57,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 {
@@ -102,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;
@@ -112,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,
@@ -121,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>
@@ -129,7 +150,8 @@ export default (
} }
} }
return { return {
Provider: CellEditProvider, Provider: CellEditProvider
Consumer: CellEditContext.Consumer
}; };
}; };
export const Consumer = CellEditContext.Consumer;

View 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>
);
};

View File

@@ -44,6 +44,8 @@ export default (_, onStartEdit) =>
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
}; };
@@ -79,16 +81,41 @@ export default (_, onStartEdit) =>
}, 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);

View File

@@ -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>
); );

View 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;
};

View File

@@ -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());
}); });
}); });

View File

@@ -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
);
});
});
});

View 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);
});
});
});

View 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>
);
}
}

View File

@@ -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>
); );

View 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>
);

View File

@@ -0,0 +1,81 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { ToggleList } = ColumnToggle;
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
const { ToggleList } = ColumnToggle;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View 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>
);

View 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>
);

View File

@@ -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 } />
) )
}]; }];

View File

@@ -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>
);

View File

@@ -1,13 +1,14 @@
import React from 'react'; import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter, dateFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block'; import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common'; import { stockGenerator } from 'utils/common';
const products = productsGenerator(8); const products = stockGenerator(8);
let nameFilter; let nameFilter;
let priceFilter; let priceFilter;
let stockDateFilter;
const columns = [{ const columns = [{
dataField: 'id', dataField: 'id',
@@ -22,25 +23,36 @@ const columns = [{
}) })
}, { }, {
dataField: 'price', dataField: 'price',
text: 'Product Price', text: 'Price',
filter: textFilter({ filter: textFilter({
getFilter: (filter) => { getFilter: (filter) => {
priceFilter = filter; priceFilter = filter;
} }
}) })
}, {
dataField: 'inStockDate',
text: 'InStock Date',
formatter: cell => cell.toString(),
filter: dateFilter({
getFilter: (filter) => {
stockDateFilter = filter;
}
})
}]; }];
const handleClick = () => { const handleClick = () => {
nameFilter(''); nameFilter('');
priceFilter(''); priceFilter('');
stockDateFilter();
}; };
const sourceCode = `\ const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter, dateFilter } from 'react-bootstrap-table2-filter';
let nameFilter; let nameFilter;
let priceFilter; let priceFilter;
let stockDateFilter;
const columns = [{ const columns = [{
dataField: 'id', dataField: 'id',
@@ -55,17 +67,27 @@ const columns = [{
}) })
}, { }, {
dataField: 'price', dataField: 'price',
text: 'Product Price', text: 'Price',
filter: textFilter({ filter: textFilter({
getFilter: (filter) => { getFilter: (filter) => {
priceFilter = filter; priceFilter = filter;
} }
}) })
}, {
dataField: 'inStockDate',
text: 'InStock Date',
formatter: cell => cell.toString(),
filter: dateFilter({
getFilter: (filter) => {
stockDateFilter = filter;
}
})
}]; }];
const handleClick = () => { const handleClick = () => {
nameFilter(''); nameFilter('');
priceFilter(''); priceFilter('');
stockDateFilter();
}; };
export default () => ( export default () => (

View File

@@ -0,0 +1,81 @@
/* eslint eqeqeq: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(8);
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
class Table extends React.Component {
filterByPrice = filterVal =>
products.filter(product => product.price == filterVal);
render() {
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter({
onFilter: this.filterByPrice
})
}];
return (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
/>
</div>
);
}
}
`;
export default class Table extends React.Component {
filterByPrice = filterVal =>
products.filter(product => product.price == filterVal);
render() {
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter({
onFilter: this.filterByPrice
})
}];
return (
<div>
<h2>Implement a eq filter on product price column</h2>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);
}
}

View File

@@ -0,0 +1,57 @@
/* eslint no-console: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(8);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter({
onFilter: filterVal => console.log(`Filter Value: ${filterVal}`)
})
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter({
onFilter: filterVal => console.log(\`Filter Value: $\{filterVal}\`)
})
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
`;
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -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>
);

View File

@@ -0,0 +1,135 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columnsdt = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const CustomToggleList = ({
columns,
onColumnToggle,
toggles
}) => (
<div className="btn-group btn-group-toggle btn-group-vertical" data-toggle="buttons">
{
columns
.map(column => ({
...column,
toggle: toggles[column.dataField]
}))
.map(column => (
<button
type="button"
key={ column.dataField }
className={ \`btn btn-warning \${column.toggle ? 'active' : ''}\` }
data-toggle="button"
aria-pressed={ column.toggle ? 'true' : 'false' }
onClick={ () => onColumnToggle(column.dataField) }
>
{ column.text }
</button>
))
}
</div>
);
<ToolkitProvider
keyField="id"
data={ products }
columns={ columnsdt }
columnToggle
>
{
props => (
<div>
<CustomToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
`;
const CustomToggleList = ({
columns,
onColumnToggle,
toggles
}) => (
<div className="btn-group btn-group-toggle btn-group-vertical" data-toggle="buttons">
{
columns
.map(column => ({
...column,
toggle: toggles[column.dataField]
}))
.map(column => (
<button
type="button"
key={ column.dataField }
className={ `btn btn-warning ${column.toggle ? 'active' : ''}` }
data-toggle="button"
aria-pressed={ column.toggle ? 'true' : 'false' }
onClick={ () => onColumnToggle(column.dataField) }
>
{ column.text }
</button>
))
}
</div>
);
export default () => (
<div>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columnsdt }
columnToggle
>
{
props => (
<div>
<CustomToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,81 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { ToggleList } = ColumnToggle;
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
hidden: true
}, {
dataField: 'price',
text: 'Product Price',
hidden: true
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
const { ToggleList } = ColumnToggle;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
hidden: true
}, {
dataField: 'price',
text: 'Product Price',
hidden: true
}];
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable { ...props.baseProps } />
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable { ...props.baseProps } />
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,81 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { ToggleList } = ColumnToggle;
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
const { ToggleList } = ColumnToggle;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,91 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { ToggleList } = ColumnToggle;
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
const { ToggleList } = ColumnToggle;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList
contextual="success"
className="list-custom-class"
btnClassName="list-btn-custom-class"
{ ...props.columnToggleProps }
/>
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList
contextual="success"
className="list-custom-class"
btnClassName="list-btn-custom-class"
{ ...props.columnToggleProps }
/>
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -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>

View File

@@ -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) {

View File

@@ -0,0 +1,70 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import { productsGenerator } from 'utils/common';
const ProductList = (props) => {
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name',
filter: textFilter({
defaultValue: '1'
})
},
{
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}
];
return (
<div style={ { paddingTop: '20px' } }>
<h1 className="h2">Products</h1>
<BootstrapTable
keyField="id"
data={ props.products }
columns={ columns }
filter={ filterFactory() }
/>
</div>
);
};
export default class DataContainer extends React.Component {
state = {
products: productsGenerator(3)
};
loadData = () => {
this.setState({
products: productsGenerator(14)
});
}
render() {
return (
<div>
<button
onClick={ this.loadData }
style={ {
fontSize: '20px',
position: 'absolute',
left: '200px',
top: '40px'
} }
>
Load Data
</button>
<ProductList products={ this.state.products } />
</div>
);
}
}

View File

@@ -0,0 +1,80 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import { productsGenerator } from 'utils/common';
const { SearchBar } = Search;
const ProductList = (props) => {
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
}
];
return (
<div style={ { paddingTop: '20px' } }>
<h1 className="h2">Products</h1>
<ToolkitProvider
keyField="id"
data={ props.products }
columns={ columns }
search={ { defaultSearch: '2101' } }
>
{
toolkitprops => (
<div>
<SearchBar { ...toolkitprops.searchProps } />
<BootstrapTable
striped
hover
{ ...toolkitprops.baseProps }
/>
</div>
)
}
</ToolkitProvider>
</div>
);
};
export default class DataContainer extends React.Component {
state = {
products: productsGenerator(3)
};
loadData = () => {
this.setState({
products: productsGenerator(14)
});
}
render() {
return (
<div>
<button
onClick={ this.loadData }
style={ {
fontSize: '20px',
position: 'absolute',
left: '200px',
top: '40px'
} }
>
Load Data
</button>
<ProductList products={ this.state.products } />
</div>
);
}
}

View File

@@ -0,0 +1,68 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import { productsGenerator } from 'utils/common';
const ProductList = (props) => {
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name',
filter: textFilter()
},
{
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}
];
return (
<div style={ { paddingTop: '20px' } }>
<h1 className="h2">Products</h1>
<BootstrapTable
keyField="id"
data={ props.products }
columns={ columns }
filter={ filterFactory() }
/>
</div>
);
};
export default class DataContainer extends React.Component {
state = {
products: []
};
loadData = () => {
this.setState({
products: productsGenerator()
});
}
render() {
return (
<div>
<button
onClick={ this.loadData }
style={ {
fontSize: '20px',
position: 'absolute',
left: '200px',
top: '40px'
} }
>
Load Data
</button>
<ProductList products={ this.state.products } />
</div>
);
}
}

View File

@@ -0,0 +1,72 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import paginationFactory from 'react-bootstrap-table2-paginator';
import { productsGenerator } from 'utils/common';
const ProductList = (props) => {
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name',
filter: textFilter({
defaultValue: '6'
})
},
{
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}
];
return (
<div style={ { paddingTop: '20px' } }>
<h1 className="h2">Products</h1>
<BootstrapTable
keyField="id"
data={ props.products }
columns={ columns }
filter={ filterFactory() }
pagination={ paginationFactory() }
/>
</div>
);
};
export default class DataContainer extends React.Component {
state = {
products: productsGenerator(60)
};
loadData = () => {
this.setState({
products: productsGenerator(14)
});
}
render() {
return (
<div>
<button
onClick={ this.loadData }
style={ {
fontSize: '20px',
position: 'absolute',
left: '200px',
top: '40px'
} }
>
Load Data
</button>
<ProductList products={ this.state.products } />
</div>
);
}
}

View File

@@ -0,0 +1,80 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import { productsGenerator } from 'utils/common';
const { SearchBar } = Search;
const ProductList = (props) => {
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
}
];
return (
<div style={ { paddingTop: '20px' } }>
<h1 className="h2">Products</h1>
<ToolkitProvider
keyField="id"
data={ props.products }
columns={ columns }
search
>
{
toolkitprops => (
<div>
<SearchBar { ...toolkitprops.searchProps } />
<BootstrapTable
striped
hover
{ ...toolkitprops.baseProps }
/>
</div>
)
}
</ToolkitProvider>
</div>
);
};
export default class DataContainer extends React.Component {
state = {
products: []
};
loadData = () => {
this.setState({
products: productsGenerator()
});
}
render() {
return (
<div>
<button
onClick={ this.loadData }
style={ {
fontSize: '20px',
position: 'absolute',
left: '200px',
top: '40px'
} }
>
Load Data
</button>
<ProductList products={ this.state.products } />
</div>
);
}
}

View File

@@ -0,0 +1,53 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID',
footerAlign: 'center',
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footerAlign: (column, colIndex) => 'right',
footer: 'Footer 2'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID',
footerAlign: 'center',
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footerAlign: (column, colIndex) => 'right',
footer: 'Footer 2'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,54 @@
/* eslint no-unused-vars: 0 */
/* eslint no-alert: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1',
footerAttrs: { title: 'ID footer column' }
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2',
footerAttrs: (column, colIndex) => ({ 'data-test': `customized data ${colIndex}` })
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1',
footerAttrs: { title: 'ID footer column' }
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2',
footerAttrs: (column, colIndex) => ({ 'data-test': \`customized data \${colIndex}\` })
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,60 @@
/* eslint no-unused-vars: 0 */
/* eslint no-alert: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2',
footerClasses: 'demo-row-odd'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3',
footerClasses: (column, colIndex) => {
if (colIndex % 2 === 0) return 'demo-row-even';
return 'demo-row-odd';
}
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2',
footerClasses: 'demo-row-odd'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3',
footerClasses: (column, colIndex) => {
if (colIndex % 2 === 0) return 'demo-row-even';
return 'demo-row-odd';
}
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,56 @@
/* eslint no-unused-vars: 0 */
/* eslint no-alert: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID',
footerEvents: {
onClick: () => alert('Click on Product ID footer column')
},
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID',
footerEvents: {
onClick: () => alert('Click on Product ID footer column')
},
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,67 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
function priceFormatter(column, colIndex) {
return (
<h5>
<strong>$$ {column.text} $$</strong>
</h5>
);
}
const columns = [
{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
},
{
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
},
{
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3',
footerFormatter: priceFormatter
}
];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
function priceFormatter(column, colIndex) {
return (
<h5><strong>$$ { column.text } $$</strong></h5>
);
}
const columns = [
// omit...
{
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3',
footerFormatter: priceFormatter
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{sourceCode}</Code>
</div>
);

View File

@@ -0,0 +1,76 @@
/* eslint no-unused-vars: 0 */
/* eslint no-alert: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2',
footerStyle: {
backgroundColor: '#c8e6c9'
}
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3',
footerStyle: (column, colIndex) => {
if (colIndex % 2 === 0) {
return {
backgroundColor: '#81c784'
};
}
return {
backgroundColor: '#c8e6c9'
};
}
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2',
footerStyle: {
backgroundColor: '#c8e6c9'
}
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3',
footerStyle: (column, colIndex) => {
if (colIndex % 2 === 0) {
return {
backgroundColor: '#81c784'
};
}
return {
backgroundColor: '#c8e6c9'
};
}
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,53 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID',
footerTitle: true,
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footerTitle: (column, colIndex) => `this is custom title for ${column.text}`,
footer: 'Footer 2'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID',
footerTitle: true,
footer: 'Footer 1'
}, {
dataField: 'name',
text: 'Product Name',
footerTitle: (column, colIndex) => \`this is custom title for \${column.text}\`,
footer: 'Footer 2'
}, {
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,61 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [
{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
},
{
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
},
{
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}
];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [
{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
},
{
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
},
{
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}
];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
footerClasses="footer-class"
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } footerClasses="footer-class" />
<Code>{sourceCode}</Code>
</div>
);

View File

@@ -0,0 +1,52 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [
{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
},
{
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
},
{
dataField: 'price',
text: 'Product Price',
footer: columnData => columnData.reduce((acc, item) => acc + item, 0)
}
];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [
// omit...
{
dataField: 'price',
text: 'Product Price',
footer: columnData => columnData.reduce((acc, item) => acc + item, 0)
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{sourceCode}</Code>
</div>
);

View File

@@ -0,0 +1,52 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [
{
dataField: 'id',
text: 'Product ID',
footer: 'Footer 1'
},
{
dataField: 'name',
text: 'Product Name',
footer: 'Footer 2'
},
{
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}
];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [
// omit...
{
dataField: 'price',
text: 'Product Price',
footer: 'Footer 3'
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{sourceCode}</Code>
</div>
);

View 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>
);

View File

@@ -0,0 +1,139 @@
/* eslint react/prefer-stateless-function: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(21);
const { SearchBar } = Search;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
class Table extends React.Component {
render() {
const options = {
custom: true,
paginationSize: 4,
pageStartIndex: 1,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
showTotal: true,
totalSize: products.length
};
const contentTable = ({ paginationProps, paginationTableProps }) => (
<div>
<PaginationListStandalone { ...paginationProps } />
<div>
<div>
<BootstrapTable
striped
hover
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
cellEdit={ cellEditFactory() }
{ ...paginationTableProps }
/>
</div>
</div>
<PaginationListStandalone { ...paginationProps } />
</div>
);
return (
<div>
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
<PaginationProvider
pagination={
paginationFactory(options)
}
>
{ contentTable }
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div >
);
}
}
`;
export default class Table extends React.Component {
render() {
const options = {
custom: true,
paginationSize: 4,
pageStartIndex: 1,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
showTotal: true,
totalSize: products.length
};
const contentTable = ({ paginationProps, paginationTableProps }) => (
<div>
<PaginationListStandalone { ...paginationProps } />
<ToolkitProvider
keyField="id"
columns={ columns }
data={ products }
search
>
{
toolkitprops => (
<div>
<SearchBar { ...toolkitprops.searchProps } />
<BootstrapTable
striped
hover
{ ...toolkitprops.baseProps }
{ ...paginationTableProps }
/>
</div>
)
}
</ToolkitProvider>
<PaginationListStandalone { ...paginationProps } />
</div>
);
return (
<div>
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
<PaginationProvider
pagination={
paginationFactory(options)
}
>
{ contentTable }
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div >
);
}
}

View 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>
);

View 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>
);

View 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>
);

View File

@@ -0,0 +1,133 @@
/* eslint react/prefer-stateless-function: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(21);
const columns = [{
dataField: 'id',
text: 'Product ID',
filter: textFilter({})
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
class Table extends React.Component {
render() {
const options = {
custom: true,
paginationSize: 4,
pageStartIndex: 1,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
showTotal: true,
totalSize: products.length
};
const contentTable = ({ paginationProps, paginationTableProps }) => (
<div>
<PaginationListStandalone { ...paginationProps } />
<div>
<div>
<BootstrapTable
striped
hover
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
cellEdit={ cellEditFactory() }
{ ...paginationTableProps }
/>
</div>
</div>
<PaginationListStandalone { ...paginationProps } />
</div>
);
return (
<div>
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
<PaginationProvider
pagination={
paginationFactory(options)
}
>
{ contentTable }
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div >
);
}
}
`;
export default class Table extends React.Component {
render() {
const options = {
custom: true,
paginationSize: 4,
pageStartIndex: 1,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
showTotal: true,
totalSize: products.length
};
const contentTable = ({ paginationProps, paginationTableProps }) => (
<div>
<PaginationListStandalone { ...paginationProps } />
<div>
<div>
<BootstrapTable
striped
hover
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
{ ...paginationTableProps }
/>
</div>
</div>
<PaginationListStandalone { ...paginationProps } />
</div>
);
return (
<div>
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
<PaginationProvider
pagination={
paginationFactory(options)
}
>
{ contentTable }
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div >
);
}
}

View 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>
);
}
}

View File

@@ -0,0 +1,190 @@
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(87);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
// ...
const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<PaginationProvider
pagination={
paginationFactory({
custom: true,
page,
sizePerPage,
totalSize
})
}
>
{
({
paginationProps,
paginationTableProps
}) => (
<div>
<div>
<p>Current Page: { paginationProps.page }</p>
<p>Current SizePerPage: { paginationProps.sizePerPage }</p>
</div>
<div>
<PaginationListStandalone
{ ...paginationProps }
/>
</div>
<BootstrapTable
remote
keyField="id"
data={ data }
columns={ columns }
onTableChange={ onTableChange }
{ ...paginationTableProps }
/>
</div>
)
}
</PaginationProvider>
</div>
);
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1,
data: products.slice(0, 10),
sizePerPage: 10
};
}
handleTableChange = (type, { page, sizePerPage }) => {
const currentIndex = (page - 1) * sizePerPage;
setTimeout(() => {
this.setState(() => ({
page,
data: products.slice(currentIndex, currentIndex + sizePerPage),
sizePerPage
}));
}, 2000);
}
render() {
const { data, sizePerPage, page } = this.state;
return (
<RemotePagination
data={ data }
page={ page }
sizePerPage={ sizePerPage }
totalSize={ products.length }
onTableChange={ this.handleTableChange }
/>
);
}
}
`;
const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<PaginationProvider
pagination={
paginationFactory({
custom: true,
page,
sizePerPage,
totalSize
})
}
>
{
({
paginationProps,
paginationTableProps
}) => (
<div>
<div>
<p>Current Page: { paginationProps.page }</p>
<p>Current SizePerPage: { paginationProps.sizePerPage }</p>
</div>
<div>
<PaginationListStandalone
{ ...paginationProps }
/>
</div>
<BootstrapTable
remote
keyField="id"
data={ data }
columns={ columns }
onTableChange={ onTableChange }
{ ...paginationTableProps }
/>
</div>
)
}
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div>
);
RemotePagination.propTypes = {
data: PropTypes.array.isRequired,
page: PropTypes.number.isRequired,
totalSize: PropTypes.number.isRequired,
sizePerPage: PropTypes.number.isRequired,
onTableChange: PropTypes.func.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1,
data: products.slice(0, 10),
sizePerPage: 10
};
}
handleTableChange = (type, { page, sizePerPage }) => {
const currentIndex = (page - 1) * sizePerPage;
setTimeout(() => {
this.setState(() => ({
page,
data: products.slice(currentIndex, currentIndex + sizePerPage),
sizePerPage
}));
}, 2000);
}
render() {
const { data, sizePerPage, page } = this.state;
return (
<RemotePagination
data={ data }
page={ page }
sizePerPage={ sizePerPage }
totalSize={ products.length }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View 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>
);
}
}

View File

@@ -0,0 +1,107 @@
/* eslint react/prefer-stateless-function: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationTotalStandalone, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(87);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationTotalStandalone, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const options = {
custom: true,
totalSize: products.length
};
<PaginationProvider
pagination={ paginationFactory(options) }
>
{
({
paginationProps,
paginationTableProps
}) => (
<div>
<PaginationTotalStandalone
{ ...paginationProps }
/>
<PaginationListStandalone
{ ...paginationProps }
/>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
{ ...paginationTableProps }
/>
</div>
)
}
</PaginationProvider>
`;
const options = {
custom: true,
totalSize: products.length
};
export default class StandalonePaginationList extends React.Component {
render() {
return (
<div>
<PaginationProvider
pagination={ paginationFactory(options) }
>
{
({
paginationProps,
paginationTableProps
}) => (
<div>
<PaginationTotalStandalone
{ ...paginationProps }
/>
<PaginationListStandalone
{ ...paginationProps }
/>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
{ ...paginationTableProps }
/>
</div>
)
}
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div>
);
}
}

View 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>
);
}
}

View File

@@ -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>

View 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>
);

View File

@@ -0,0 +1,76 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsExpandRowsGenerator } from 'utils/common';
const products = productsExpandRowsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const expandRow = {
renderer: row => (
<div>
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
<p>You can render anything here, also you can add additional data on every row object</p>
<p>expandRow.renderer callback will pass the origin row object to you</p>
</div>
),
showExpandColumn: true,
expandColumnPosition: 'right'
};
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const expandRow = {
renderer: row => (
<div>
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
<p>You can render anything here, also you can add additional data on every row object</p>
<p>expandRow.renderer callback will pass the origin row object to you</p>
</div>
),
showExpandColumn: true,
expandColumnPosition: 'right'
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
expandRow={ expandRow }
/>
`;
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
expandRow={ expandRow }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -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]
}; };

View 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>
);
}
}

View 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>
);

View File

@@ -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>

View 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>
);

View File

@@ -0,0 +1,86 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { SearchBar, ClearSearchButton } = Search;
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
const { SearchBar, ClearSearchButton } = Search;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
search
>
{
props => (
<div>
<h3>Input something at below input field:</h3>
<SearchBar { ...props.searchProps } />
<ClearSearchButton { ...props.searchProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
search
>
{
props => (
<div>
<h3>Input something at below input field:</h3>
<SearchBar { ...props.searchProps } />
<ClearSearchButton { ...props.searchProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);

View 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>&nbsp;&nbsp;Desc/Asc</span>);
else if (order === 'asc') return (<span>&nbsp;&nbsp;Desc/<font color="red">Asc</font></span>);
else if (order === 'desc') return (<span>&nbsp;&nbsp;<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>&nbsp;&nbsp;Desc/Asc</span>);
else if (order === 'asc') return (<span>&nbsp;&nbsp;Desc/<font color="red">Asc</font></span>);
else if (order === 'desc') return (<span>&nbsp;&nbsp;<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>
);

View File

@@ -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" />

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-example", "name": "react-bootstrap-table2-example",
"version": "1.0.5", "version": "1.0.18",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"private": true, "private": true,

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -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

View File

@@ -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,
@@ -63,6 +70,7 @@ export const stockGenerator = (quantity = 5) =>
Array.from({ length: quantity }, (value, index) => ({ Array.from({ length: quantity }, (value, index) => ({
id: index, id: index,
name: `Todo item ${index}`, name: `Todo item ${index}`,
price: Math.floor((Math.random() * 2) + 1),
inStockDate: inStockDate:
new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime())) new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime()))
})); }));

View File

@@ -13,11 +13,14 @@ 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';
import Bootstrap4RowSelectionTable from 'examples/bootstrap4/row-selection'; import Bootstrap4RowSelectionTable from 'examples/bootstrap4/row-selection';
import Bootstrap4PaginationTable from 'examples/bootstrap4/pagination'; import Bootstrap4PaginationTable from 'examples/bootstrap4/pagination';
import Bootstrap4ColumnToggleTable from 'examples/bootstrap4/column-toggle';
// work on columns // work on columns
import NestedDataTable from 'examples/columns/nested-data-table'; import NestedDataTable from 'examples/columns/nested-data-table';
@@ -43,6 +46,18 @@ import HeaderColumnStyleTable from 'examples/header-columns/column-style-table';
import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table'; import HeaderColumnAttrsTable from 'examples/header-columns/column-attrs-table';
import HeaderClassTable from 'examples/header-columns/header-class-table'; import HeaderClassTable from 'examples/header-columns/header-class-table';
// footer
import SimpleFooter from 'examples/footer/simple-footer';
import FunctionFooter from 'examples/footer/function-footer';
import FooterClassTable from 'examples/footer/footer-class-table';
import FooterColumnFormatTable from 'examples/footer/column-format-table';
import FooterColumnAlignTable from 'examples/footer/column-align-table';
import FooterColumnTitleTable from 'examples/footer/column-title-table.js';
import FooterColumnEventsTable from 'examples/footer/column-event-table.js';
import FooterColumnClassTable from 'examples/footer/column-class-table.js';
import FooterColumnStyleTable from 'examples/footer/column-style-table.js';
import FooterColumnAttrsTable from 'examples/footer/column-attrs-table.js';
// column filter // column filter
import TextFilter from 'examples/column-filter/text-filter'; import TextFilter from 'examples/column-filter/text-filter';
import TextFilterWithDefaultValue from 'examples/column-filter/text-filter-default-value'; import TextFilterWithDefaultValue from 'examples/column-filter/text-filter-default-value';
@@ -53,6 +68,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';
@@ -71,11 +87,14 @@ import ProgrammaticallyMultiSelectFilter from 'examples/column-filter/programmat
import CustomFilter from 'examples/column-filter/custom-filter'; import CustomFilter from 'examples/column-filter/custom-filter';
import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter'; import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter';
import ClearAllFilters from 'examples/column-filter/clear-all-filters'; import ClearAllFilters from 'examples/column-filter/clear-all-filters';
import FilterHooks from 'examples/column-filter/filter-hooks';
import CustomFilterLogic from 'examples/column-filter/custom-filter-logic';
// work on rows // work on rows
import RowStyleTable from 'examples/rows/row-style'; import RowStyleTable from 'examples/rows/row-style';
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';
@@ -83,6 +102,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';
@@ -94,12 +114,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 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';
@@ -112,7 +135,9 @@ 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';
@@ -128,17 +153,31 @@ 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 ExpandOnlyOne from 'examples/row-expand/expand-only-one';
import CustomExpandColumn from 'examples/row-expand/custom-expand-column'; import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
import ExpandColumnPosition from 'examples/row-expand/expand-column-position';
import ExpandHooks from 'examples/row-expand/expand-hooks'; import ExpandHooks from 'examples/row-expand/expand-hooks';
// pagination // pagination
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 StandalonePaginationTotal from 'examples/pagination/standalone-pagination-total';
import FullyCustomPaginationTable from 'examples/pagination/fully-custom-pagination';
import RemoteStandalonePaginationTable from 'examples/pagination/remote-standalone-pagination';
import CustomePaginationWithFilter from 'examples/pagination/custome-page-list-with-filter';
import CustomePaginationWithSearch from 'examples/pagination/custom-page-list-with-search';
// search // search
import SearchTable from 'examples/search'; import SearchTable from 'examples/search';
import ClearSearchButton from 'examples/search/clear-search-button';
import DefaultSearch from 'examples/search/default-search'; import DefaultSearch from 'examples/search/default-search';
import DefaultCustomSearch from 'examples/search/default-custom-search'; import DefaultCustomSearch from 'examples/search/default-custom-search';
import FullyCustomSearch from 'examples/search/fully-custom-search'; import FullyCustomSearch from 'examples/search/fully-custom-search';
@@ -156,6 +195,12 @@ import CustomCSVButton from 'examples/csv/custom-csv-button';
import ExportCustomData from 'examples/csv/export-custom-data'; import ExportCustomData from 'examples/csv/export-custom-data';
import CustomCSV from 'examples/csv/custom-csv'; import CustomCSV from 'examples/csv/custom-csv';
// Column toggle
import BasicColumnToggle from 'examples/column-toggle';
import DefaultVisibility from 'examples/column-toggle/default-visibility';
import StylingColumnToggle from 'examples/column-toggle/styling-toggle-list';
import CustomToggleList from 'examples/column-toggle/custom-toggle-list';
// loading overlay // loading overlay
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay'; import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
import TableOverlay from 'examples/loading-overlay/table-overlay'; import TableOverlay from 'examples/loading-overlay/table-overlay';
@@ -168,6 +213,13 @@ import RemoteSearch from 'examples/remote/remote-search';
import RemoteCellEdit from 'examples/remote/remote-celledit'; import RemoteCellEdit from 'examples/remote/remote-celledit';
import RemoteAll from 'examples/remote/remote-all'; import RemoteAll from 'examples/remote/remote-all';
// data
import LoadDataWithFilter from 'examples/data/load-data-on-the-fly-with-filter';
import LoadDataWithDefaultFilter from 'examples/data/load-data-on-the-fly-with-default-filter';
import LoadDataWithSearch from 'examples/data/load-data-on-the-fly-with-search';
import LoadDataWithDefaultSearch from 'examples/data/load-data-on-the-fly-with-default-search';
import LoadDataWithPaginationAndFilter from 'examples/data/load-data-on-the-fly-with-pagination-and-filter';
// css style // css style
import 'stories/stylesheet/tomorrow.min.css'; import 'stories/stylesheet/tomorrow.min.css';
import 'stories/stylesheet/storybook.scss'; import 'stories/stylesheet/storybook.scss';
@@ -178,8 +230,7 @@ import '../../react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.
// import bootstrap style by given version // import bootstrap style by given version
import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style'; import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style';
storiesOf('Welcome', module) storiesOf('Welcome', module).add('react bootstrap table 2 ', () => <Welcome />);
.add('react bootstrap table 2 ', () => <Welcome />);
storiesOf('Basic Table', module) storiesOf('Basic Table', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
@@ -189,13 +240,16 @@ 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))
.add('Sort table with bootstrap 4', () => <Bootstrap4DefaultSortTable />) .add('Sort table with bootstrap 4', () => <Bootstrap4DefaultSortTable />)
.add('Row selection table with bootstrap 4', () => <Bootstrap4RowSelectionTable />) .add('Row selection table with bootstrap 4', () => <Bootstrap4RowSelectionTable />)
.add('Pagination table with bootstrap 4', () => <Bootstrap4PaginationTable />); .add('Pagination table with bootstrap 4', () => <Bootstrap4PaginationTable />)
.add('Column Toggle with bootstrap 4', () => <Bootstrap4ColumnToggleTable />);
storiesOf('Work on Columns', module) storiesOf('Work on Columns', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
@@ -252,14 +306,31 @@ 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('Clear All Filters', () => <ClearAllFilters />); .add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
.add('Clear All Filters', () => <ClearAllFilters />)
.add('Filter Hooks', () => <FilterHooks />)
.add('Implement custom filter logic', () => <CustomFilterLogic />);
storiesOf('Work on Rows', module) storiesOf('Work on Rows', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.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('Footer', module)
.addDecorator(bootstrapStyle())
.add('Simple Footer', () => <SimpleFooter />)
.add('Function Footer', () => <FunctionFooter />)
.add('Column Formatter', () => <FooterColumnFormatTable />)
.add('Column Align', () => <FooterColumnAlignTable />)
.add('Column Title', () => <FooterColumnTitleTable />)
.add('Column Events', () => <FooterColumnEventsTable />)
.add('Customize Column Class', () => <FooterColumnClassTable />)
.add('Customize Column Style', () => <FooterColumnStyleTable />)
.add('Customize Column HTML attribute', () => <FooterColumnAttrsTable />)
.add('Footer Class', () => <FooterClassTable />);
storiesOf('Sort Table', module) storiesOf('Sort Table', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Enable Sort', () => <EnableSortTable />) .add('Enable Sort', () => <EnableSortTable />)
@@ -267,6 +338,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 />);
@@ -279,12 +351,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('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 />)
@@ -298,7 +373,9 @@ 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 />)
@@ -315,25 +392,46 @@ 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('Expand Only One Row at The Same Time', () => <ExpandOnlyOne />)
.add('Custom Expand Indicator', () => <CustomExpandColumn />) .add('Custom Expand Indicator', () => <CustomExpandColumn />)
.add('Expand Column Position', () => <ExpandColumnPosition />)
.add('Expand Hooks', () => <ExpandHooks />); .add('Expand Hooks', () => <ExpandHooks />);
storiesOf('Pagination', module) storiesOf('Pagination', module)
.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('Standalone Pagination Total', () => <StandalonePaginationTotal />)
.add('Fully Custom Pagination', () => <FullyCustomPaginationTable />)
.add('Remote Fully Custom Pagination', () => <RemoteStandalonePaginationTable />)
.add('Custom Pagination with Filter', () => <CustomePaginationWithFilter />)
.add('Custom Pagination with Search', () => <CustomePaginationWithSearch />);
storiesOf('Table Search', module) storiesOf('Table Search', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Basic Search Table', () => <SearchTable />) .add('Basic Search Table', () => <SearchTable />)
.add('Clear Search Button', () => <ClearSearchButton />)
.add('Default Search Table', () => <DefaultSearch />) .add('Default Search Table', () => <DefaultSearch />)
.add('Default Custom Search', () => <DefaultCustomSearch />) .add('Default Custom Search', () => <DefaultCustomSearch />)
.add('Fully Custom Search', () => <FullyCustomSearch />) .add('Fully Custom Search', () => <FullyCustomSearch />)
.add('Search Fromatted Value', () => <SearchFormattedData />) .add('Search Fromatted Value', () => <SearchFormattedData />)
.add('Custom Search Value', () => <CustomSearchValue />); .add('Custom Search Value', () => <CustomSearchValue />);
storiesOf('Column Toggle', module)
.addDecorator(bootstrapStyle())
.add('Basic Column Toggle', () => <BasicColumnToggle />)
.add('Default Visibility', () => <DefaultVisibility />)
.add('Styling Column Toggle', () => <StylingColumnToggle />)
.add('Custom Column Toggle', () => <CustomToggleList />);
storiesOf('Export CSV', module) storiesOf('Export CSV', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Basic Export CSV', () => <ExportCSV />) .add('Basic Export CSV', () => <ExportCSV />)
@@ -359,3 +457,11 @@ storiesOf('Remote', module)
.add('Remote Search', () => <RemoteSearch />) .add('Remote Search', () => <RemoteSearch />)
.add('Remote Cell Editing', () => <RemoteCellEdit />) .add('Remote Cell Editing', () => <RemoteCellEdit />)
.add('Remote All', () => <RemoteAll />); .add('Remote All', () => <RemoteAll />);
storiesOf('Data', module)
.addDecorator(bootstrapStyle())
.add('Load data with Filter', () => <LoadDataWithFilter />)
.add('Load data with Default Filter', () => <LoadDataWithDefaultFilter />)
.add('Load data with Search', () => <LoadDataWithSearch />)
.add('Load data with Default Search', () => <LoadDataWithDefaultSearch />)
.add('Load data with Filter and Pagination', () => <LoadDataWithPaginationAndFilter />);

View File

@@ -13,4 +13,8 @@
.header-class { .header-class {
background-color: $green-lighten-4; background-color: $green-lighten-4;
}
.footer-class {
background-color: $green-lighten-4;
} }

View File

@@ -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;

View File

@@ -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

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-filter", "name": "react-bootstrap-table2-filter",
"version": "1.0.0", "version": "1.1.4",
"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": {

View File

@@ -42,10 +42,11 @@ class DateFilter extends Component {
// export onFilter function to allow users to access // export onFilter function to allow users to access
if (getFilter) { if (getFilter) {
getFilter((filterVal) => { getFilter((filterVal) => {
this.dateFilterComparator.value = filterVal.comparator; const nullableFilterVal = filterVal || { date: null, comparator: null };
this.inputDate.value = dateParser(filterVal.date); this.dateFilterComparator.value = nullableFilterVal.comparator;
this.inputDate.value = nullableFilterVal.date ? dateParser(nullableFilterVal.date) : null;
this.applyFilter(filterVal.date, filterVal.comparator); this.applyFilter(nullableFilterVal.date, nullableFilterVal.comparator);
}); });
} }
} }

View File

@@ -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,

View File

@@ -17,14 +17,19 @@ export default (
class FilterProvider extends React.Component { class FilterProvider extends React.Component {
static propTypes = { static propTypes = {
data: PropTypes.array.isRequired, data: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired columns: PropTypes.array.isRequired,
dataChangeListener: PropTypes.object
} }
constructor(props) { constructor(props) {
super(props); super(props);
this.currFilters = {}; this.currFilters = {};
this.onFilter = this.onFilter.bind(this); this.onFilter = this.onFilter.bind(this);
this.doFilter = this.doFilter.bind(this);
this.onExternalFilter = this.onExternalFilter.bind(this); this.onExternalFilter = this.onExternalFilter.bind(this);
this.state = {
data: props.data
};
} }
componentDidMount() { componentDidMount() {
@@ -33,6 +38,16 @@ export default (
} }
} }
componentWillReceiveProps(nextProps) {
let nextData = nextProps.data;
if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.props.data)) {
nextData = this.doFilter(nextProps);
}
this.setState({
data: nextData
});
}
onFilter(column, filterType, initialize = false) { onFilter(column, filterType, initialize = false) {
return (filterVal) => { return (filterVal) => {
// watch out here if migration to context API, #334 // watch out here if migration to context API, #334
@@ -64,7 +79,13 @@ export default (
return; return;
} }
this.forceUpdate(); let result;
if (filter.props.onFilter) {
result = filter.props.onFilter(filterVal);
}
result = this.doFilter(this.props, result);
this.setState({ data: result });
}; };
} }
@@ -74,14 +95,21 @@ export default (
}; };
} }
render() { doFilter(props, customResult) {
let { data } = this.props; let result = customResult;
if (!isRemoteFiltering()) {
data = filters(data, this.props.columns, _)(this.currFilters); const { dataChangeListener, data, columns } = props;
result = result || filters(data, columns, _)(this.currFilters);
if (dataChangeListener) {
dataChangeListener.emit('filterChanged', result.length);
} }
return result;
}
render() {
return ( return (
<FilterContext.Provider value={ { <FilterContext.Provider value={ {
data, data: this.state.data,
onFilter: this.onFilter, onFilter: this.onFilter,
onExternalFilter: this.onExternalFilter onExternalFilter: this.onExternalFilter
} } } }

View File

@@ -44,7 +44,9 @@ describe('FilterContext', () => {
const handleFilterChange = jest.fn(); const handleFilterChange = jest.fn();
function shallowContext( function shallowContext(
enableRemote = false enableRemote = false,
tableColumns = columns,
dataChangeListener,
) { ) {
mockBase.mockReset(); mockBase.mockReset();
handleFilterChange.mockReset(); handleFilterChange.mockReset();
@@ -56,8 +58,9 @@ describe('FilterContext', () => {
return ( return (
<FilterContext.Provider <FilterContext.Provider
columns={ columns } columns={ tableColumns }
data={ data } data={ data }
dataChangeListener={ dataChangeListener }
> >
<FilterContext.Consumer> <FilterContext.Consumer>
{ {
@@ -225,6 +228,84 @@ describe('FilterContext', () => {
}); });
}); });
describe('if filter.props.onFilter is defined', () => {
const filterVal = '3';
const onFilter = jest.fn();
const customColumns = columns.map((column, i) => {
if (i === 1) {
return {
...column,
filter: textFilter({ onFilter })
};
}
return column;
});
beforeEach(() => {
wrapper = shallow(shallowContext(false, customColumns));
wrapper.render();
instance = wrapper.instance();
});
it('should call filter.props.onFilter correctly', () => {
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
expect(onFilter).toHaveBeenCalledTimes(1);
expect(onFilter).toHaveBeenCalledWith(filterVal);
});
});
describe('if filter.props.onFilter is defined and return an undefined data', () => {
const mockReturn = [{
id: 1,
name: 'A'
}];
const filterVal = 'A';
const onFilter = jest.fn().mockReturnValue(mockReturn);
const customColumns = columns.map((column, i) => {
if (i === 1) {
return {
...column,
filter: textFilter({ onFilter })
};
}
return column;
});
beforeEach(() => {
wrapper = shallow(shallowContext(false, customColumns));
wrapper.render();
instance = wrapper.instance();
});
it('should call filter.props.onFilter correctly', () => {
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
expect(onFilter).toHaveBeenCalledTimes(1);
expect(onFilter).toHaveBeenCalledWith(filterVal);
});
it('should set state.data correctly', () => {
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
expect(instance.state.data).toEqual(mockReturn);
});
});
describe('when props.dataChangeListener is defined', () => {
const filterVal = '3';
const newDataLength = 0;
const dataChangeListener = { emit: jest.fn() };
beforeEach(() => {
wrapper = shallow(shallowContext(false, columns, dataChangeListener));
wrapper.render();
instance = wrapper.instance();
});
it('should call dataChangeListener.emit correctly', () => {
instance.onFilter(columns[1], FILTER_TYPE.TEXT)(filterVal);
expect(dataChangeListener.emit).toHaveBeenCalledWith('filterChanged', newDataLength);
});
});
describe('combination', () => { describe('combination', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallow(shallowContext()); wrapper = shallow(shallowContext());

View File

@@ -37,4 +37,197 @@ 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)
### Fully Customization
If you want to customize the pagination component completely, you may get interesting on following solutions:
* Standalone
* Non-standalone
`react-bootstrap-table2-paginator` have a `PaginationProvider` which is a react context and that will be easier to customize the pagination components under the scope of `PaginationProvider`. Let's introduce it step by step:
#### 1. Import PaginationProvider
```js
import paginationFactory, { PaginationProvider } from 'react-bootstrap-table2-paginator';
```
#### 2. Declare custom and totalSize in pagination option:
```js
const paginationOption = {
custom: true,
totalSize: products.length
};
```
#### 3. 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 which solution you like: standalone or non-standalone ?
#### 4.1 Use Standalone Component
`react-bootstrap-table2-paginator` provider three standalone components:
* Size Per Page Dropdwn Standalone
* Pagination List Standalone
* Pagination Total Standalone
When render each standalone, you just need to pass the `paginationProps` props to standalone component:
```js
import paginationFactory, {
PaginationProvider,
PaginationListStandalone,
SizePerPageDropdownStandalone,
PaginationTotalStandalone
} from 'react-bootstrap-table2-paginator';
<PaginationProvider
pagination={ paginationFactory(options) }
>
{
({
paginationProps,
paginationTableProps
}) => (
<div>
<SizePerPageDropdownStandalone
{ ...paginationProps }
/>
<PaginationTotalStandalone
{ ...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.
#### 4.2 Customization Everything
If you choose to custom the pagination component by yourself, the `paginationProps` will be important for you. Becasue you have to know for example how to change page or what's the current page etc. Hence, following is all the props in `paginationProps` object:
```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.

View File

@@ -1,6 +1,27 @@
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';
import PaginationTotalStandalone from './src/pagination-total-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, PaginationTotalStandalone };

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-paginator", "name": "react-bootstrap-table2-paginator",
"version": "1.0.2", "version": "2.0.3",
"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": {

View File

@@ -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
};
};

View 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
});

View File

@@ -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
}; };

View File

@@ -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,
@@ -140,8 +135,8 @@ export default ExtendBase =>
calculateSizePerPageStatus() { calculateSizePerPageStatus() {
const { sizePerPageList } = this.props; const { sizePerPageList } = this.props;
return sizePerPageList.map((_sizePerPage) => { return sizePerPageList.map((_sizePerPage) => {
const pageText = _sizePerPage.text || _sizePerPage; const pageText = typeof _sizePerPage.text !== 'undefined' ? _sizePerPage.text : _sizePerPage;
const pageNumber = _sizePerPage.value || _sizePerPage; const pageNumber = typeof _sizePerPage.value !== 'undefined' ? _sizePerPage.value : _sizePerPage;
return { return {
text: `${pageText}`, text: `${pageText}`,
page: pageNumber page: pageNumber

View File

@@ -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;
} }

View 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 }
/>
);
}
};

View 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;

View 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)));

View File

@@ -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;

Some files were not shown because too many files have changed in this diff Show More