Compare commits

..

101 Commits

Author SHA1 Message Date
AllenFang
a556bd23ef Publish
- react-bootstrap-table2-editor@0.0.3
 - react-bootstrap-table2-example@0.0.3
 - react-bootstrap-table2-filter@0.0.3
 - react-bootstrap-table2-overlay@0.0.3
 - react-bootstrap-table2-paginator@0.0.3
 - react-bootstrap-table-next@0.0.3
2018-01-21 13:59:30 +08:00
AllenFang
b2e6bf93fb tweak pagination factory name 2018-01-20 17:53:58 +08:00
AllenFang
5f7c55aad4 drop start scripts 2018-01-20 15:27:08 +08:00
AllenFang
b4f7028b8b no publish 2018-01-20 15:27:08 +08:00
AllenFang
50a5bd3694 refine file name 2018-01-20 15:27:08 +08:00
AllenFang
9b3abac56d react-bootstrap-table2 -> react-bootstrap-table-next 2018-01-20 14:55:58 +08:00
AllenFang
1ef006e4c2 add README.md 2018-01-20 14:44:59 +08:00
AllenFang
42339b76aa tweak package.json 2018-01-20 13:34:27 +08:00
AllenFang
0d3b76b6a3 README.md 2018-01-20 11:21:11 +08:00
Allen
28240391bb Merge pull request #167 from react-bootstrap-table/Chun-MingChen-prod-setup
Production build
2018-01-18 23:17:37 +08:00
AllenFang
1cedea567c remove lerna-changelog 2018-01-18 22:56:18 +08:00
AllenFang
a9dd05d7cc fix entry point changed 2018-01-18 22:53:51 +08:00
AllenFang
41d76a08ce gulp build for style, scripts and umd 2018-01-18 21:49:33 +08:00
AllenFang
5d0b0af97a build sass 2018-01-16 22:54:02 +08:00
AllenFang
4bd73056d0 babel build 2018-01-16 00:04:14 +08:00
AllenFang
ec705f2651 umd build 2018-01-14 23:43:21 +08:00
AllenFang
3a8390c49e react-bootstrap-table2-example depend other packages via webpack resolver instead of node modules 2018-01-14 18:29:27 +08:00
AllenFang
afc742c205 no babel-cli build per repo 2018-01-14 15:56:39 +08:00
AllenFang
be4211b3c9 no publish to gh-pages 2018-01-14 15:53:27 +08:00
AllenFang
6c0fc4ffb4 Merge branch 'prod-setup' of https://github.com/Chun-MingChen/react-bootstrap-table2 into Chun-MingChen-prod-setup 2018-01-14 15:41:46 +08:00
Allen
55fe0075b1 Merge pull request #165 from react-bootstrap-table/enhance/cell-edit-as-package
react-bootstrap-table2-editor
2018-01-07 14:18:59 +08:00
AllenFang
618346b845 patch docs for cell edit 2018-01-07 14:07:17 +08:00
AllenFang
e46d83762d fix EditingCell liftcycle bug 2018-01-07 14:02:50 +08:00
AllenFang
9428f2d9b7 refine cell edit tests 2018-01-07 11:20:49 +08:00
AllenFang
21344ec4b3 refine cell edit stories 2018-01-07 11:20:49 +08:00
AllenFang
39be018327 move cell edit logic to react-bootstrap-table2-editor 2018-01-07 11:20:32 +08:00
Chun-MingChen
3649f83eaf select lerna-changelog to generate change log 2018-01-07 01:46:52 +08:00
Chun-MingChen
a37ef6883d compile with babel 2018-01-07 01:46:52 +08:00
Chun-MingChen
383cfbab57 add package babel-cli 2018-01-07 01:29:13 +08:00
Chun-MingChen
cb1041b9d7 auto release for storybook
* deploy subdirectory of storybook-static to branch gh-pages
2018-01-07 01:29:13 +08:00
Chun-MingChen
6e4ca34626 add dependency git-directory-deploy
* Deploy a subdirectory from a git repo to a different branch.
2018-01-06 19:43:28 +08:00
Chun-MingChen
19cca1215f add dependency rimraf
* clean built files for gh_pages
2018-01-06 19:43:03 +08:00
Allen
6913434714 fix #161
Refine cell edit remote mode
2018-01-06 13:48:07 +08:00
AllenFang
d5f7ae5edb refined docs for remote cell edit 2018-01-04 23:45:40 +08:00
AllenFang
beafef9661 patch tests for refining remote cell edit 2018-01-04 23:45:40 +08:00
AllenFang
a50a12426a refine remote cell edit 2018-01-04 23:42:17 +08:00
Allen
fcf7800f96 fix #152
implement remote sorting
2017-12-28 17:58:18 +08:00
AllenFang
01337f50a7 implement remote sorting 2017-12-27 23:31:16 +08:00
Allen
bdfc4ebcad Merge pull request #158 from react-bootstrap-table/enhance/refactoring
Refarcotring Wrapper
2017-12-25 17:46:23 +08:00
AllenFang
fb81595f73 refactoring wrapper mechanism 2017-12-25 17:32:14 +08:00
AllenFang
3bfeec7946 fix bug for onTableChange argument change 2017-12-25 17:32:14 +08:00
AllenFang
4c89f91a83 implement remote resolver 2017-12-25 17:32:14 +08:00
Allen
90bea38900 Merge pull request #156 refine remote filter and pagination
Implement remote filter
2017-12-24 16:24:56 +08:00
AllenFang
2fbc84e36e pathc docs for remote mode 2017-12-24 16:16:40 +08:00
AllenFang
c4eb2f835f refine remote mode on filter and pagination 2017-12-24 16:16:40 +08:00
AllenFang
e14c596b8c refine remote examples 2017-12-24 16:16:40 +08:00
Allen
5cbeae704b Fix #154
* headerFormatter should custom whole the header cell

* add story for headerFormatter with filter and sort

* patch docs for column.headerFormatter
2017-12-23 14:52:04 +08:00
Allen
80b1ac3370 fix #147
Implement TextFilter
2017-12-23 14:00:37 +08:00
AllenFang
64b3710ae0 docs for column filter 2017-12-23 13:54:03 +08:00
AllenFang
867465c123 fix typo 2017-12-23 13:53:36 +08:00
AllenFang
024dcf8c12 add some stories for text filter 2017-12-16 17:55:25 +08:00
AllenFang
51ef91b066 add story for column.filterValue 2017-12-16 17:55:25 +08:00
AllenFang
ad98cfe1a8 implement column.filterValue 2017-12-16 17:55:25 +08:00
AllenFang
c01db26428 add story for text filter 2017-12-16 17:55:25 +08:00
AllenFang
00185b80ca add react-bootstrap-table2-filter 2017-12-16 17:55:25 +08:00
AllenFang
ba93a6ce9c All the downstream wrapper for filter wrapper should checking props.isDataChange 2017-12-16 17:55:25 +08:00
AllenFang
297c5ad438 fix pagination bug 2017-12-16 15:16:03 +08:00
AllenFang
7016e55472 implement filter 2017-12-16 15:16:03 +08:00
Allen
1879d77cdf Merge pull request #150 from react-bootstrap-table/document-pagination
[Document] patch for pagination
2017-12-16 13:57:03 +08:00
Chun-MingChen
472f5d887c layout and wording beautify 2017-12-16 13:36:23 +08:00
AllenFang
861809d10c render filter in bootstrap table 2017-12-13 21:45:02 +08:00
Chun-MingChen
48004e1cb5 patch for pagination document
* required props for remote mode
2017-12-10 20:45:53 +08:00
Allen
da907d46f0 fix liftcycle issue (#149) 2017-12-10 19:32:43 +08:00
Allen
4d04b755ad fix wrong HOC for SortWrapper (#148) 2017-12-10 15:05:58 +08:00
chunming
00f1105c8d Development/sorted classes and style (#136)
* fix missing defaultSorted props for default sort sample

* implement customized classes for sorted header

* [test] test for sorted header classes

* implement customized style for sorted header

* [test] test for sorted header style

* update document

* add missing props check and fix typo

* seperate sorting style and header into two props

* [test] add test case if column.headerStyle and column.headerClasses were defined

* implement customized header style and classes in column level

* [test] test for customized header style and classes in column level

* [DOC] document for customized classes and styles

* sample for customized classes and styles

* typo fix for document

* tuning the wording for test and documents
2017-12-10 13:53:03 +08:00
Allen
574a3146fc funcaitonal store (#146) 2017-12-09 14:56:09 +08:00
Allen
ff31b2fca5 fix #144
implement loading overlay
2017-12-03 23:01:57 +08:00
AllenFang
32b187ff9f no --pure-lockfile --ignore-scripts 2017-12-03 18:32:26 +08:00
AllenFang
a363764ce9 patch docs for overlay 2017-12-03 17:59:21 +08:00
AllenFang
fab06bf599 patch docs for remote 2017-12-03 17:35:00 +08:00
AllenFang
70303617fb add stories for loading overlay 2017-12-03 17:13:05 +08:00
AllenFang
dc096a6c4e implement loading overlay 2017-12-03 17:11:36 +08:00
Allen
dfc0e15086 fix #140
Implement remote pagination
2017-12-02 18:20:32 +08:00
AllenFang
d43b3d61ed add story remote pagination 2017-12-02 16:01:33 +08:00
AllenFang
28f1bdb49f patch tests for remote pagination 2017-12-02 16:01:33 +08:00
AllenFang
f9abcf42f4 implement remote pagination 2017-12-02 15:45:57 +08:00
Allen
47f86dff4a patch docs for pagination (#139) 2017-11-19 23:42:54 +08:00
Allen
3c88364efe fix #135
* init react-bootstrap-table2-paginator

* add react-bootstrap-table2-paginator as dependency

* no container

* handle for wrapping pagination component

* add style for paginator addon

* add story for pagination

* implement pagination list

* constants maintain in core package

* implement sizePerPage dropdown

* fix unalign for sizePerPage dropdown and pagination list

* allow to return array from render(react@16 new feature)

* implement pagination hooks

* add story for pagination hooks

* fixed dependencies version and upgrade enzyme

* Shallow renderer no longer calls componentDidMount because DOM refs are not available

* classNames -> className for TextEditor

* add tests for pagination

* fix react-bootstrap-table can't be resolved in other modules

* implement custom page button title

* add test for page button title

* fix bug when sizePerPageList is an object array

* add story for custom pagination

* remove necessary component extends

* move pagination options to react-bootstrap-table2-paginator

* refine pagination stories

* implement hideSizePerPage

* implement hidePageListOnlyOnePage

* fix multiple same key warning

* remove help

* support start from react@^16
2017-11-19 17:42:20 +08:00
chunming
79a81e87a5 Bugfix/row selection (#131)
* bugfix for missing radio button when single selection

* [test] correct and group the test for row selection

* re-order for better position
2017-11-05 17:37:30 +08:00
Allen
316b4e5302 fix #133
* implement row events

* add story for row event

* add tests for row events

* patch docs for rowEvents
2017-10-30 16:07:59 +08:00
Allen
6110663075 fix #128
* implement custom row classes

* add story for customizing row classes

* add test for rowClasses

* patch docs for rowClasses
2017-10-30 14:24:39 +08:00
Allen
19dc4d3984 fix #129
* implement custom row style

* add story for custom row style

* add tests for rowStyle

* patch docs for rowStyle
2017-10-29 18:17:20 +08:00
Allen
e1e8c00271 fix #64
* implement default sort

* add story for default sort

* add test for default sort

* patch docs for default sort

* a workaround to avoid render twice by story.add
2017-10-29 16:58:37 +08:00
Allen
ab305a7db2 fix #119
* implement selectRow.hideSelectColumn

* add story for selectRow.hideSelectColumn

* add tests for selectRow.hideSelectColumn

* patch docs for selectRow.hideSelectColumn
2017-10-29 14:58:33 +08:00
chunming
ca02af3d6a logs messages on the story panel (#123)
* ref: https://github.com/storybooks/storybook-addon-console
2017-10-29 14:01:03 +08:00
Allen
974f129aad fix #116
* implement selection hook

* add story for selection hooks

* add tests for selection hooks

* add missing test for store.setSelectedRowKeys(array)

* patch docs for selection hooks
2017-10-26 03:49:35 -05:00
Joshua
cf142d3b39 Improve CONTRIBUTING doc
* Improve CONTRIBUTING doc

* Correct some typos and grammar errors

* Improve docs/README.md
2017-10-26 01:36:13 -05:00
Allen
985a1713ae fix #111
* implement selectRow.clickToSelect and selectRow.clickToEdit

* add selectRow.clickToSelect and selectRow.clickToEdit stories

* add clickToSelect to row selection examples for easier to select row

* refine selectRow.nonSelectable

* patch tests for selectRow.clickToSelect and selectRow.clickToEdit

* patch docs for selectRow.clickToSelect and selectRow.clickToEdit
2017-10-26 01:35:09 -05:00
Allen
bbeb122af1 fix wrong higher order wrapping (#112)
* fix wrong higher order wrapping

* fix tests for wrong wrapper design
2017-10-24 00:56:59 -05:00
Allen
b16da90ae9 fix #108
* implement selectRow.bgColor

* add story for selectRow.bgColor

* add testing for selectRow.bgColor

* patch docs for selectRow.bgColor
2017-10-23 03:08:30 -05:00
Allen
afc41879ee fix #106
* implement selectRow.nonSelectable

* add story for selectRow.nonSelectable

* add testing for selectRow.nonSelectable

* refine tests about row selection

* patch docs for selectRow.nonSelectable
2017-10-20 03:25:48 -05:00
Allen
10f06dca10 fix #104
* implement row seleciton style and class

* add testing for row selection style and class

* refine select row test

* add stories for row selection style and class

* add docs for row selection style and class

* patch for wrong docs
2017-10-20 00:44:25 -05:00
Allen
cb6410bbe4 fix #101
* implement cell editor style/class

* add stories for custom cell editor style and class

* patch testing for cell editor style and class

* patch docs for cell editor style and class
2017-10-18 09:15:41 -05:00
Allen
afef2adcaf add missing HeaderCell.propTypes 2017-10-18 02:09:24 -05:00
Allen
0440c63c66 always jsx-curly-spacing 2017-10-18 01:31:12 -05:00
Allen
4f7a3d7eaf refine row selection
* adjust propType order

* rename for resolving selectRow prop

* refine row selection

* refine document
2017-10-18 01:13:06 -05:00
Allen
f52baa47ea refine sort logic to wrapper
* move sort relevant components to sort dir

* refine sort logic to wrapper
2017-10-17 12:17:53 -05:00
Allen
0ca6335d92 refine row selection to wrapper
* refine row selection code base to wrapper

* refine testing for moving row selection code base to wrapper
2017-10-17 10:23:36 -05:00
Allen
6887c12d11 no need BootstrapTableful anymore
* refine BootstrapTableful -> BootstrapTable

* refine stateful-layer as container
2017-10-17 04:30:23 -05:00
Allen
bc67dfcd23 Refine the code base for cell edit 2017-10-17 03:42:26 -05:00
Allen
7a5b88bcf6 fix #63
* support async cell editing

* refine cellEdit.onUpdate and cellEdit.editing

* refine cell edit

* add redux

* add stories for async cell edit

* fix test case and patch tests for async cell editing

* patch docs for cellEdit prop

* fix bug produced by rebasing lol
2017-10-17 02:27:48 -05:00
202 changed files with 14794 additions and 2404 deletions

View File

@@ -11,7 +11,7 @@
],
"rules": {
"comma-dangle": ["error", "never"],
"react/jsx-curly-spacing": 0,
"react/jsx-curly-spacing": [2, "always"],
"react/forbid-prop-types": 0,
"react/jsx-filename-extension": 0,
"react/jsx-space-before-closing": 0,

7
.gitignore vendored
View File

@@ -15,3 +15,10 @@ lerna-debug.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# gh-pages
storybook-static
# build
lib
dist

7
.npmignore Normal file
View File

@@ -0,0 +1,7 @@
node_modules
.DS_Store
*~
*.sublime-project
*.sublime-workspace
*.idea
*.iml

View File

@@ -17,4 +17,4 @@ before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash -s
- export PATH="$HOME/.yarn/bin:$PATH"
install: yarn install --pure-lockfile --ignore-scripts
install: yarn install

View File

@@ -1,21 +1,22 @@
# Contributing
# Issues
Before opening an issue, please make sure your problem/request doesn't exist. When you open issue, please provide the following information if possible:
Before opening an issue, please make sure your problem or request doesn't exist. When opening an issue, please provide the following information if possible:
* Example code or repo (please keep it simple and minimal)
* Steps to reproduce
* `react-bootstrap-table2` version
* Steps to reproduce.
* `react-bootstrap-table2` version.
Anyway, you're welcome to open an issue to ask questions or discuss about a feature request.
Additionally, asking questions and requesting new features are welcomed via [issue tracker](https://github.com/react-bootstrap-table/react-bootstrap-table2/issues).
# Pull Requests
Check [here](./docs/development.md) for getting started with development.
* When you want to implement a new feature, please let us know (via issues).
* Please run tests before opening a PR and also remember to test the actual business logic.
* If your PR is trying to fix a bug, please describe the bug number with hashtag when creating the PR.
* We recommend filing an [issue](https://github.com/react-bootstrap-table/react-bootstrap-table2/issues) before you implement any new features.
* Please ensure that all the test suites have passed before submitting a PR. Besides, always test the actual business logic.
* If your PR is trying to fix a bug, please describe the details as much as you could and tag the bug number with hashtag.
# For the members of react-bootstrap-table2 org
* Please convert the ticket to issue when is ticket moved from `Backlog` to `Ready` in project.
* Please write documentation if any new API/feature/props is changed or added.
* Please add a story example if any new feature is implemented
* Please convert the ticket to issue when the ticket has moved from `Backlog` to `Ready`.
* Please update the docs if any API, feature or component props was changed or added. The code and docs should always be in sync.
* Please add a story example if any new feature was implemented.

View File

@@ -1,25 +1,12 @@
# react-bootstrap-table2
Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
## The problems/features I want to solve
* Performance
* Fully compatiable with bootstrap 3 and 4(`react-bootstrap-table@4.0.0` already done)
* Clean Code and Testing
* Decrease the size of bundled file
* **Split module/functionality from core module, make core module more lightweight**
* Use [`storybook`](https://github.com/storybooks/storybook) to build examples
* Support the aggregation(summary) view
* Support the table footer
* Support column/row span on header and body
* Support sticky header
* Support table section([react-bootstrap-table#721](https://github.com/AllenFang/react-bootstrap-table/pull/721))
* Handle events well
* Fix unalign issues
* Make **stateless** table more easy to use(`react-bootstrap-table` alread have `remote` mode but have some bugs)
* Customizable table
* Support the nested data([react-bootstrap-table#50](https://github.com/AllenFang/react-bootstrap-table/issues/50◊))
* Consider to support column resize
* Consider to make animation on `react-bootstrap-table2` more easy
## Development
Please check [development guide](./docs/development.md).
## Usage
See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html).
## Roadmap
See [release plans](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/release-plan.html).
## The feature may lost on react-bootstrap-table
* Have a great chance that I don't support the vertical scrollbar on table

View File

@@ -1,6 +1,6 @@
# Documents
# Documentation
## Props on BootstrapTable
## BootstrapTable Props
#### Required
* [keyField (**required**)](#keyField)
@@ -8,6 +8,8 @@
* [columns (**required**)](#columns)
#### Optional
* [remote](#remote)
* [loading](#loading)
* [caption](#caption)
* [striped](#striped)
* [bordered](#bordered)
@@ -15,56 +17,261 @@
* [condensed](#condensed)
* [cellEdit](#cellEdit)
* [selectRow](#selectRow)
* [rowStyle](#rowStyle)
* [rowClasses](#rowClasses)
* [rowEvents](#rowEvents)
* [defaultSorted](#defaultSorted)
* [pagination](#pagination)
* [filter](#filter)
* [onTableChange](#onTableChange)
### <a name='keyField'>keyField(**required**) - [String]</a>
`keyField` is a prop to tell `react-bootstrap-table2` which column is unigue key.
Tells `react-bootstrap-table2` which column is unique.
### <a name='data'>data(**required**) - [Array]</a>
Assign your table data via `data` prop. It only accept an Array object.
Provides data for your table. It accepts a single Array object.
### <a name='columns'>columns(**required**) - [Object]</a>
`columns` props accept an Array object, please see [columns definition](./columns.md) for more detail.
Accepts a single Array object, please see [columns definition](./columns.md) for more detail.
### <a name='remote'>remote - [Bool | Object]</a>
Default is `false`, if enable`remote`, you are suppose to handle all the table change events, like: pagination, insert, filtering etc.
This is a chance that you can connect to your remote server or database to manipulate your data.
For flexibility reason, you can control what functionality should be handled on remote via a object return:
```js
remote={ {
filter: true,
pagination: true,
filter: true,
sort: true,
cellEdit: true
} }
```
In above case, only column filter will be handled on remote.
> Note: when remote is enable, you are suppose to give [`onTableChange`](#onTableChange) prop on `BootstrapTable`
> It's the only way to communicate to your remote server and update table states.
A special case for remote pagination:
```js
remote={ { pagination: true, filter: false, sort: false } }
```
There is a apecial case for remote pagination, even you only specified the paignation need to handle as remote, `react-bootstrap-table2` will handle all the table changes(filter, sort etc) as remote mode, because `react-bootstrap-table2` only know the data of current page, but filtering, searching or sort need to work on overall datas.
### <a name='loading'>loading - [Bool]</a>
Telling if table is loading or not, for example: waiting data loading, filtering etc. It's **only** valid when [`remote`](#remote) is enabled.
When `loading` is `true`, `react-bootstrap-table2` will attend to render a overlay on table via [`overlay`](#overlay) prop, if [`overlay`](#overlay) prop is not given, `react-bootstrap-table2` will ignore the overlay rendering.
### <a name='overlay'>overlay - [Function]</a>
`overlay` accept a factory funtion which should returning a higher order component. By default, `react-bootstrap-table2-overlay` can be a good option for you:
```sh
$ npm install react-bootstrap-table2-overlay
```
```js
import overlayFactory from 'react-bootstrap-table2-overlay';
<BootstrapTable
data={ data }
columns={ columns }
loading={ true } //only loading is true, react-bootstrap-table will render overlay
overlay={ overlayFactory() }
/>
```
Actually, `react-bootstrap-table-overlay` is depends on [`react-loading-overlay`](https://github.com/derrickpelletier/react-loading-overlay) and `overlayFactory` just a factory function and you can pass any props which available for `react-loading-overlay`:
```js
overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) }
```
### <a name='caption'>caption - [String | Node]</a>
Same as [caption tag](https://www.w3schools.com/TAgs/tag_caption.asp) in HTML. You can give a String or a React JSX.
Same as HTML [caption tag](https://www.w3schools.com/TAgs/tag_caption.asp), you can set it as String or a React JSX.
### <a name='striped'>striped - [Bool]</a>
Same as `.table-striped` class for adding zebra-stripes to a table
Same as bootstrap `.table-striped` class for adding zebra-stripes to a table.
### <a name='bordered'>bordered - [Bool]</a>
Same as `.table-bordered` class for adding borders on all sides of the table and cells
Same as bootstrap `.table-bordered` class for adding borders to a table and table cells.
### <a name='hover'>hover - [Bool]</a>
Same as `.table-hover` class for adding a hover effect (grey background color) on table rows
Same as bootstrap `.table-hover` class for adding mouse hover effect (grey background color) on table rows.
### <a name='condensed'>condensed - [Bool]</a>
Same as `.table-condensed` class for makeing a table more compact by cutting cell padding in half
Same as bootstrap `.table-condensed` class for making a table more compact by cutting cell padding in half.
### <a name='cellEdit'>cellEdit - [Object]</a>
Assign a valid `cellEdit` object can enable the cell editing on the cell. The default usage is click/dbclick to trigger cell editing and press `ENTER` to save cell or press `ESC` to cancel editing.
> Note: The `keyField` column can't be edited
Following is a `cellEdit` object:
```js
{
mode: 'click',
blurToSave: true,
timeToCloseMessage: 2500,
onEditing: (rowId, dataField, newValue) => { ... },
beforeSaveCell: (oldValue, newValue, row, column) => { ... },
afterSaveCell: (oldValue, newValue, row, column) => { ... },
nonEditableRows: () => { ... }
}
```
#### <a name='cellEdit.mode'>cellEdit.mode - [String]</a>
`cellEdit.mode` possible value is `click` and `dbclick`. **It's required value** that tell `react-bootstrap-table2` how to trigger the cell editing.
#### <a name='cellEdit.blurToSave'>cellEdit.blurToSave - [Bool]</a>
Default is `false`, enable it will be able to save the cell automatically when blur from the cell editor.
#### <a name='cellEdit.nonEditableRows'>cellEdit.nonEditableRows - [Function]</a>
`cellEdit.nonEditableRows` accept a callback function and expect return an array which used to restrict all the columns of some rows as non-editable. So the each item in return array should be rowkey(`keyField`)
#### <a name='cellEdit.timeToCloseMessage'>cellEdit.timeToCloseMessage - [Function]</a>
If a [`column.validator`](./columns.md#validator) defined and the new value is invalid, `react-bootstrap-table2` will popup a alert at the bottom of editor. `cellEdit.timeToCloseMessage` is a chance to let you decide how long the alert should be stay. Default is 3000 millisecond.
Makes table cells editable, please see [cellEdit definition](./cell-edit.md) for more detail.
### <a name='selectRow'>selectRow - [Object]</a>
Pass prop `selectRow` to enable row selection. For more detail, please navigate to [row selection document](./row-selection.md).
Makes table rows selectable, please see [selectRow definition](./row-selection.md) for more detail.
### <a name='rowStyle'>rowStyle = [Object | Function]</a>
Custom the style of table rows:
```js
<BootstrapTable data={ data } columns={ columns } rowStyle={ { backgroundColor: 'red' } } />
```
This prop also accept a callback function for flexible to custom row style:
```js
const rowStyle = (row, rowIndex) => {
return { ... };
};
<BootstrapTable data={ data } columns={ columns } rowStyle={ rowStyle } />
```
### <a name='rowClasses'>rowClasses = [String | Function]</a>
Custom the style of table rows:
```js
<BootstrapTable data={ data } columns={ columns } rowClasses="custom-row-class" />
```
This prop also accept a callback function for flexible to custom row style:
```js
const rowClasses = (row, rowIndex) => {
return 'custom-row-class';
};
<BootstrapTable data={ data } columns={ columns } rowClasses={ rowClasses } />
```
### <a name='rowEvents'>rowEvents - [Object]</a>
Custom the events on row:
```js
const rowEvents = {
onClick: (e) => {
....
}
};
<BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } />
```
### <a name='defaultSorted'>defaultSorted - [Array]</a>
`defaultSorted` accept an object array which allow you to define the default sort columns when first render.
```js
const defaultSorted = [{
dataField: 'name', // if dataField is not match to any column you defined, it will be ignored.
order: 'desc' // desc or asc
}];
```
### <a name='pagination'>pagination - [Object]</a>
`pagination` allow user to render a pagination panel on the bottom of table. But pagination funcitonality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-paginator` additionaly.
```sh
$ npm install react-bootstrap-table2-paginator --save
```
After installation of `react-bootstrap-table2-paginator`, you can enable pagination on `react-bootstrap-table2` easily:
```js
import paginator from 'react-bootstrap-table2-paginator';
// omit...
<BootstrapTable data={ data } columns={ columns } pagination={ paginator() } />
```
`paginator` is a function actually and allow to pass some pagination options, following we list all the available options:
```js
paginator({
page, // Specify the current page. It's necessary when remote is enabled
sizePerPage, // Specify the size per page. It's necessary when remote is enabled
totalSize, // Total data size. It's necessary when remote is enabled
pageStartIndex: 0, // first page will be 0, default is 1
paginationSize: 3, // the pagination bar size, default is 5
sizePerPageList: [ {
text: '5', value: 5
}, {
text: '10', value: 10
}, {
text: 'All', value: products.length
} ], // A numeric array is also available: [5, 10]. the purpose of above example is custom the text
withFirstAndLast: false, // hide the going to first and last page button
alwaysShowAllBtns: true, // always show the next and previous page button
firstPageText: 'First', // the text of first page button
prePageText: 'Prev', // the text of previous page button
nextPageText: 'Next', // the text of next page button
lastPageText: 'Last', // the text of last page button
nextPageTitle: 'Go to next', // the title of next page button
prePageTitle: 'Go to previous', // the title of previous page button
firstPageTitle: 'Go to first', // the title of first page button
lastPageTitle: 'Go to last', // the title of last page button
hideSizePerPage: true, // hide the size per page dorpdown
hidePageListOnlyOnePage: true, // hide pagination bar when only one page, default is false
onPageChange: (page, sizePerPage) => {}, // callback function when page was changing
onSizePerPageChange: (sizePerPage, page) => {}, // callback function when page size was changing
})
```
### <a name='filter'>filter - [Object]</a>
`filter` allow user to filter data by column. However, filter funcitonality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-filter` firstly.
```sh
$ npm install react-bootstrap-table2-filter --save
```
After installation of `react-bootstrap-table2-filter`, you can configure filter on `react-bootstrap-table2` easily:
```js
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
// omit...
const columns = [ {
dataField: 'id',
text: 'Production ID'
}, {
dataField: 'name',
text: 'Production Name',
filter: textFilter() // apply text filter
}, {
dataField: 'price',
text: 'Production Price'
} ];
<BootstrapTable data={ data } columns={ columns } filter={ filterFactory() } />
```
### <a name='onTableChange'>onTableChange - [Function]</a>
This callback function will be called when [`remote`](#remote) enabled only.
```js
const onTableChange = (type, newState) => {
// handle any data change here
}
<BootstrapTable data={ data } columns={ columns } onTableChange={ onTableChange } />
```
There's only two arguments will be passed to `onTableChange`: `type` and `newState`:
`type` is tell you what kind of functionality to trigger this table's change: available values at the below:
* `filter`
* `pagination`
* `sort`
* `cellEdit`
Following is a shape of `newState`
```js
{
page, // newest page
sizePerPage, // newest sizePerPage
sortField, // newest sort field
sortOrder, // newest sort order
filters, // an object which have current filter status per column
data, // when you enable remote sort, you may need to base on data to sort if data is filtered/searched
cellEdit: { // You can only see this prop when type is cellEdit
rowId,
dataField,
newValue
}
}
```

74
docs/cell-edit.md Normal file
View File

@@ -0,0 +1,74 @@
# Cell Editing
Before start to use cell edit, please remember to install `react-bootstrap-table2-editor`
```sh
$ npm install react-bootstrap-table2-editor --save
```
# Properties on cellEdit prop
* [mode (**required**)](#mode)
* [blurToSave](#blurToSave)
* [nonEditableRows](#nonEditableRows)
* [timeToCloseMessage](#timeToCloseMessage)
* [beforeSaveCell](#beforeSaveCell)
* [afterSaveCell](#afterSaveCell)
* [errorMessage](#errorMessage)
* [onErrorMessageDisappear](#onErrorMessageDisappear)
## <a name='cellEdit'>cellEdit - [Object]</a>
Assign a valid `cellEdit` object can enable the cell editing on the cell. The default usage is click/dbclick to trigger cell editing and press `ENTER` to save cell or press `ESC` to cancel editing.
> Note: The `keyField` column can't be edited
Following is the shape of `cellEdit` object:
```js
{
mode: 'click',
blurToSave: true,
timeToCloseMessage: 2500,
errorMessage: '',
beforeSaveCell: (oldValue, newValue, row, column) => { ... },
afterSaveCell: (oldValue, newValue, row, column) => { ... },
onErrorMessageDisappear: () => { ... },
nonEditableRows: () => { ... }
}
```
### <a name='mode'>cellEdit.mode - [String]</a>
`cellEdit.mode` possible value is `click` and `dbclick`. **It's required value** that tell `react-bootstrap-table2` how to trigger the cell editing.
### <a name='blurToSave'>cellEdit.blurToSave - [Bool]</a>
Default is `false`, enable it will be able to save the cell automatically when blur from the cell editor.
### <a name='nonEditableRows'>cellEdit.nonEditableRows - [Function]</a>
`cellEdit.nonEditableRows` accept a callback function and expect return an array which used to restrict all the columns of some rows as non-editable. So the each item in return array should be rowkey(`keyField`)
### <a name='timeToCloseMessage'>cellEdit.timeToCloseMessage - [Function]</a>
If a [`column.validator`](./columns.md#validator) defined and the new value is invalid, `react-bootstrap-table2` will popup a alert at the bottom of editor. `cellEdit.timeToCloseMessage` is a chance to let you decide how long the alert should be stay. Default is 3000 millisecond.
### <a name='beforeSaveCell'>cellEdit.beforeSaveCell - [Function]</a>
This callback function will be called before triggering cell update.
```js
const cellEdit = {
// omit...
beforeSaveCell: (oldValue, newValue, row, column) => { ... }
}
```
### <a name='afterSaveCell'>cellEdit.afterSaveCell - [Function]</a>
This callback function will be called after updating cell.
```js
const cellEdit = {
// omit...
afterSaveCell: (oldValue, newValue, row, column) => { ... }
};
```
### <a name='errorMessage'>cellEdit.errorMessage - [String]</a>
This prop is not often used. Only used when you want to keep the error message in your application state and also handle the cell editing on remote mode.
### <a name='onErrorMessageDisappear'>cellEdit.onErrorMessageDisappear - [Function]</a>
This callback function will be called when error message discard so that you can sync the newest error message to your state if you have.

View File

@@ -25,22 +25,28 @@ Available properties in a column object:
* [headerEvents](#headerEvents)
* [headerAlign](#headerAlign)
* [headerAttrs](#headerAttrs)
* [headerSortingClasses](#headerSortingClasses)
* [headerSortingStyle](#headerSortingStyle)
* [editable](#editable)
* [validator](#validator)
* [editCellStyle](#editCellStyle)
* [editCellClasses](#editCellClasses)
* [filter](#filter)
* [filterValue](#filterValue)
Following is a most simplest and basic usage:
```js
const rows = [ { id: 1, name: '...', price: '102' } ];
const columns = [ {
dataField: id,
text: Production ID
dataField: 'id',
text: 'Production ID'
}, {
dataField: name,
text: Production Name
dataField: 'name',
text: 'Production Name'
}, {
dataField: price,
text: Production Price
dataField: 'price',
text: 'Production Price'
}
];
```
@@ -67,7 +73,7 @@ dataField: 'address.city'
```
## <a name='text'>column.text (**required**) - [String]</a>
`text` will be apply as the column text in header column, if your header is not only text and you want to customize your header column, please check [`column.headerFormatter`](#headerFormatter)
`text` will be the column text in header column by default, if your header is not only text or you want to customize the header column, please check [`column.headerFormatter`](#headerFormatter)
## <a name='hidden'>column.hidden - [Bool]</a>
`hidden` allow you to hide column when `true` given.
@@ -81,10 +87,19 @@ dataField: 'address.city'
* [`formatExtraData`](#formatExtraData)
## <a name='headerFormatter'>column.headerFormatter - [Function]</a>
`headerFormatter` allow you to customize the header column and only accept a callback function which take two arguments and a JSX/String are expected for return.
`headerFormatter` allow you to customize the header column and only accept a callback function which take three arguments and a JSX/String are expected for return.
* `column`: column object itself
* `colIndex`
* `column`: current column object itself
* `colIndex`: index of current column
* `components`: an object which contain all of other react element, like sort caret or filter etc.
The third argument: `components` have following specified properties:
```js
{
sortElement, // sort caret element, it will not be undefined when you enable sort on this column
filterElement // filter element, it will not be undefined when you enable column.filter on this column
}
```
## <a name='formatExtraData'>column.formatExtraData - [Any]</a>
It's only used for [`column.formatter`](#formatter), you can define any value for it and will be passed as fourth argument for [`column.formatter`](#formatter) callback function.
@@ -116,7 +131,7 @@ It's availabe to have custom class on table column:
classes: 'id-custom-cell'
}
```
In addition, `classes` also accept a callback function which have more power to custom the css class on each columns. This callback function take `4` arguments and a `string` is expect to return:
In addition, `classes` also accept a callback function which have more power to custom the css class on each columns. This callback function take **4** arguments and a `String` is expected to return::
```js
@@ -133,7 +148,7 @@ In addition, `classes` also accept a callback function which have more power to
**Return value**
A new `String` will be the result of element class.
A new `String` will be the result as element class.
## <a name='headerClasses'>column.headerClasses - [String | Function]</a>
It's similar to [`column.classes`](#classes), `headerClasses` is availabe to have customized class on table header column:
@@ -170,7 +185,7 @@ It's availabe to have custom style on table column:
}
```
In addition, similar to [`column.classes`](#classes), `style` also accept a callback function which have more power to customize the `inline style` on each columns. This callback function takes `4` arguments and an `Object` is expect to return:
In addition, similar to [`column.classes`](#classes), `style` also accept a callback function which have more power to customize the `inline style` on each columns. This callback function takes **4** arguments and an `Object` is expect to return:
```js
@@ -200,7 +215,7 @@ It's availabe to have customized inline-style on table header column:
}
```
Moreover, it also accept a callback function which takes 2 arguments and an `Object` is expect to return:
Moreover, it also accept a callback function which takes **2** arguments and an `Object` is expect to return:
```js
{
@@ -218,7 +233,7 @@ A new `Object` will be the result of element headerStyle.
## <a name='title'>column.title - [Bool | Function]</a>
`react-bootstrap-table2` is disable [`HTML title`](https://www.w3schools.com/tags/tag_title.asp) as default. You can assign `title` as `true` to enable the HTML title on table column and take `cell content` as default value. Additionally, you could customize title via a callback. It takes `4` arguments and a `String` is expect to return:
`react-bootstrap-table2` is disable [`HTML title`](https://www.w3schools.com/tags/tag_title.asp) as default. You can assign `title` as `true` to enable the HTML title on table column and take `cell content` as default value. Additionally, you could customize title via a callback. It takes **4** arguments and a `String` is expect to return:
```js
@@ -267,7 +282,7 @@ A new `String` will be the result of element headerTitle.
## <a name='align'>column.align - [String | Function]</a>
You can configure the [CSS text-align](https://www.w3schools.com/cssref/pr_text_text-align.asp) for table column by `align` property.
Besides, `align` also accept a callback function for dynamically setting text align. It takes `4` arguments and a `String` is expect to return:
Besides, `align` also accept a callback function for dynamically setting text align. It takes **4** arguments and a `String` is expect to return:
```js
{
@@ -370,14 +385,14 @@ Not only `Object`, `callback function` is also acceptable. It takes `4` argument
A new `Object` will be the result of element HTML attributes.
#### * Caution
> Caution:
If `column.classes`, `column.style`, `column.title`, `column.hidden` or `column.align` was given at the same time, property `attrs` has lower priorty and it will be overwrited.
> If `column.classes`, `column.style`, `column.title`, `column.hidden` or `column.align` was given at the same time, property `attrs` has lower priorty and it will be overwrited.
```js
{
// omit...
title: true, // it will be chosen.
title: true, // get higher priority
attrs: { title: 'test' }
}
```
@@ -394,7 +409,7 @@ If `column.classes`, `column.style`, `column.title`, `column.hidden` or `column.
}
```
Additionally, customize the header attributes by a `2-arguments` callback function:
Additionally, customize the header attributes by a **2** arguments callback function:
```js
{
@@ -417,6 +432,35 @@ A new `Object` will be the result of element headerAttrs.
> Same as [column.attrs](#attrs), it has lower priority and will be
> overwrited when other props related to HTML attributes were given.
### <a name='headerSortingClasses'>headerSortingClasses - [String | Function]</a>
`headerSortingClasses` allows to customize `class` for header cell when this column is sorting.
```js
const headerSortingClasses = 'demo-sorting';
```
Furthermore, it also accepts a callback which takes **4** arguments and `String` is expected to return:
```js
const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => { ... }
```
* `column`: The value of current column.
* `sortOrder`: The order of current sorting
* `isLastSorting`: Is the last one of sorted columns.
* `colIndex`: The index of the current column being processed in BootstrapTable.
### <a name='headerSortingStyle'>headerSortingStyle - [Object | Function]</a>
It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize the style of header cell when this column is sorting. A style `Object` and `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return:
```js
const sortingHeaderStyle = {
backgroundColor: 'red'
};
```
## <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`.
@@ -450,4 +494,87 @@ The return value can be a bool or an object. If your valiation is pass, return `
valid: false,
message: 'SOME_REASON_HERE'
}
```
## <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:
**Parameters**
* `cell`: The value of current cell.
* `row`: The object of `row` being processed in the `BootstrapTable`.
* `rowIndex`: The index of the current `row` being processed in the `BootstrapTable`.
* `colIndex`: The index of the current `column` being processed in `BootstrapTable`.
```js
{
editCellStyle: { ... }
}
```
Or take a callback function
```js
{
editCellStyle: (cell, row, rowIndex, colIndex) => {
// it is suppose to return an object
}
}
```
## <a name='editCellClasses'>column.editCellClasses - [String | Function]</a>
You can use `column.editCellClasses` to add custom class on `<td>` when cell editing. It's same as [`column.editCellStyle`](#editCellStyle) which also accept a callback function to able to custom your class more flexible. Following is the arguments of this callback function: `cell`, `row`, `rowIndex`, `colIndex`.
```js
{
editCellClasses: 'custom-class'
}
```
Or take a callback function
```js
{
editCellClasses: (cell, row, rowIndex, colIndex) => {
// it is suppose to return a string
}
}
```
## <a name='filter'>column.filter - [Object]</a>
Configure `column.filter` will able to setup a column level filter on the header column. Currently, `react-bootstrap-table2` support following filters:
* Text(`textFilter`)
We have a quick example to show you how to use `column.filter`:
```
import { textFilter } from 'react-bootstrap-table2-filter';
// omit...
{
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}
```
For some reason of simple customization, `react-bootstrap-table2` allow you to pass some props to filter factory function. Please check [here](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/master/packages/react-bootstrap-table2-filter/README.md) for more detail tutorial.
## <a name='filterValue'>column.filterValue - [Function]</a>
Sometimes, if the cell/column value that you don't want to filter on them, you can define `filterValue` to return a actual value you wanna be filterd:
**Parameters**
* `cell`: The value of current cell.
* `row`: The value of current row.
**Return value**
A final `String` value you want to be filtered.
```js
// omit...
{
dataField: 'price',
text: 'Product Price',
filter: textFilter(),
filterValue: (cell, row) => owners[cell]
}
```

View File

@@ -9,7 +9,7 @@ $ lerna bootstrap # ./node_modules/.bin/lerna bootstrap
```
### Development
```bash
$ npm start
$ npm run storybook
```
### Launch StoryBook

View File

@@ -1,32 +1,37 @@
# Row selection
`react-bootstrap-table2` supports the row selection feature. By passing prop `selectRow ` to enable row selection. When you enable this feature, `react-bootstrap-table2` will append a new selection column at first.
`react-bootstrap-table2` supports the row selection feature. By passing prop `selectRow` to enable row selection. When you enable this feature, `react-bootstrap-table2` will append a new selection column at first.
## Required
* [mode (**required**)](#mode)
## Available properties
## Optional
* [style](#style)
* [classes)](#classes)
* [bgColor](#bgColor)
* [nonSelectable)](#nonSelectable)
* [clickToSelect)](#clickToSelect)
* [clickToEdit](#clickToEdit)
* [onSelect](#onSelect)
* [onSelectAll](#onSelectAll)
* [hideSelectColumn](#hideSelectColumn)
The following are available properties in `selectRow`:
#### Required
* [mode (required)](#mode)
#### Optional
## <a name="mode">selectRow.mode - [String]</a>
### <a name="mode">selectRow.mode - [String]</a>
Specifying the selection way for `single(radio)` or `multiple(checkbox)`. If `radio` was assigned, there will be a radio button in the selection column; otherwise, the `checkbox` instead.
#### values
* `radio`
* `checkbox`
* **radio**
* **checkbox**
#### examples
```js
const selectRowProp = {
const selectRow = {
mode: 'radio' // single row selection
};
<BootstrapTableful
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
@@ -35,14 +40,144 @@ const selectRowProp = {
```
```js
const selectRowProp = {
const selectRow = {
mode: 'checkbox' // multiple row selection
};
<BootstrapTableful
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRowProp }
/>
```
### <a name='style'>selectRow.style - [Object | Function]</a>
`selectRow.style` allow you to have custom style on selected rows:
```js
const selectRow = {
mode: 'checkbox',
style: { background: 'red' }
};
```
If you wanna more flexible customization, `selectRow.style` also accept a function:
```js
const selectRow = {
mode: 'checkbox',
style: (row, rowIndex) => { return ...; }
};
```
### <a name='classes'>selectRow.classes - [String | Function]</a>
`selectRow.classes` allow you to add css class on selected rows:
```js
const selectRow = {
mode: 'checkbox',
classes: 'custom-class'
};
```
If you wanna more flexible customization, `selectRow.classes` also accept a function:
```js
const selectRow = {
mode: 'checkbox',
classes: (row, rowIndex) => { return ...; }
};
```
### <a name='bgColor'>selectRow.bgColor - [String | Function]</a>
The backgroud color when row is selected
```js
const selectRow = {
mode: 'checkbox',
bgColor: 'red'
};
```
There's also a more good way to custom it:
```js
const selectRow = {
mode: 'checkbox',
bgColor: (row, rowIndex) => {
return ....; // return a color code
}
};
```
### <a name='nonSelectable'>selectRow.nonSelectable - [Array]</a>
This prop allow you to restrict some rows which can not be selected by user. `selectRow.nonSelectable` accept an rowkeys array.
```js
const selectRow = {
mode: 'checkbox',
nonSelectable: [1, 3 ,5]
};
```
### <a name='clickToSelect'>selectRow.clickToSelect - [Bool]</a>
Allow user to select row by clicking on the row.
```js
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
```
> 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)
### <a name='clickToEdit'>selectRow.clickToEdit - [Bool]</a>
Able to click to edit cell and select row
```js
const selectRow = {
mode: 'checkbox',
clickToSelect: true
clickToEdit: true
};
```
### <a name='onSelect'>selectRow.onSelect - [Function]</a>
This callback function will be called when a row is select/unselect and pass following three arguments:
`row`, `isSelect` and `rowIndex`.
```js
const selectRow = {
mode: 'checkbox',
onSelect: (row, isSelect, rowIndex) => {
// ...
}
};
```
### <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`.
```js
const selectRow = {
mode: 'checkbox',
onSelectAll: (isSelect, results) => {
// ...
}
};
```
### <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`
```js
const selectRow = {
mode: 'radio',
hideSelectColumn: true,
clickToSelect: true,
bgColor: 'red'
};
```

8
enzyme-setup.js Normal file
View File

@@ -0,0 +1,8 @@
import Adapter from 'enzyme-adapter-react-16';
import { configure } from 'enzyme';
const configureEnzyme = () => {
configure({ adapter: new Adapter() });
};
configureEnzyme();

84
gulpfile.babel.js Normal file
View File

@@ -0,0 +1,84 @@
import gulp from 'gulp';
import babel from 'gulp-babel';
import sass from 'gulp-sass';
import cleanCSS from 'gulp-clean-css';
import cleanDir from 'gulp-clean';
import rename from 'gulp-rename';
import shell from 'gulp-shell';
const LIB = 'lib';
const DIST = 'dist';
const TEST = 'test';
const PKG_PATH = './packages';
const NODE_MODULES = 'node_modules';
const JS_PKGS = [
'react-bootstrap-table2',
'react-bootstrap-table2-editor',
'react-bootstrap-table2-filter',
'react-bootstrap-table2-overlay',
'react-bootstrap-table2-paginator'
].reduce((pkg, curr) => `${curr}|${pkg}`, '');
const JS_SKIPS = `+(${TEST}|${LIB}|${DIST}|${NODE_MODULES})`;
const STYLE_PKGS = [
'react-bootstrap-table2',
'react-bootstrap-table2-paginator'
].reduce((pkg, curr) => `${curr}|${pkg}`, '');
const STYLE_SKIPS = `+(${NODE_MODULES})`;
function clean() {
return gulp
.src(`./packages/+(${JS_PKGS})/+(${LIB}|${DIST})`, { allowEmpty: true })
.pipe(cleanDir());
}
function scripts() {
return gulp
.src([
`./packages/+(${JS_PKGS})/**/*.js`,
`!packages/+(${JS_PKGS})/${JS_SKIPS}/**/*.js`
])
.pipe(babel())
.pipe(rename((path) => {
if (path.dirname.indexOf('src') > -1) {
path.dirname = path.dirname.replace('src', `${LIB}/src`);
} else {
path.dirname += `/${LIB}`;
}
}))
.pipe(gulp.dest(PKG_PATH));
}
function styles() {
return gulp
.src([
`./packages/+(${STYLE_PKGS})/style/**/*.scss`,
`!packages/+(${STYLE_PKGS})/${STYLE_SKIPS}/**/*.scss`
])
.pipe(sass().on('error', sass.logError))
.pipe(rename((path) => {
path.dirname = path.dirname.replace('style', DIST);
}))
.pipe(gulp.dest(PKG_PATH))
.pipe(cleanCSS({ compatibility: 'ie8' }))
.pipe(rename((path) => {
path.extname = '.min.css';
}))
.pipe(gulp.dest(PKG_PATH));
}
function umd() {
return gulp.src('./webpack.prod.config.babel.js')
.pipe(shell(['webpack --config <%= file.path %>']));
}
const buildJS = gulp.parallel(umd, scripts);
const buildCSS = styles;
const build = gulp.series(clean, gulp.parallel(buildJS, buildCSS));
gulp.task('prod', build);
gulp.task('default', build);

View File

@@ -3,5 +3,5 @@
"packages": [
"packages/*"
],
"version": "0.0.0"
"version": "independent"
}

View File

@@ -5,64 +5,75 @@
"main": "index.js",
"scripts": {
"postinstall": "lerna bootstrap",
"start": "node -r babel-register ./node_modules/.bin/webpack-dev-server --config webpack.config.babel.js",
"build": "./node_modules/.bin/gulp prod",
"lint": "eslint ./packages --ext .js --ext .jsx --ignore-path .gitignore",
"pretest": "yarn lint --cache",
"test": "jest",
"test:coverage": "jest --coverage",
"test:watch": "jest --watch",
"storybook": "cd ./packages/react-bootstrap-table2-example && yarn storybook"
"storybook": "cd ./packages/react-bootstrap-table2-example && yarn storybook",
"gh-pages:clean": "cd ./packages/react-bootstrap-table2-example && yarn gh-pages:clean",
"gh-pages:build": "cd ./packages/react-bootstrap-table2-example && yarn gh-pages:build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/react-bootstrap-table/react-bootstrap-table2.git"
},
"author": "",
"license": "ISC",
"author": "AllenFang",
"contributors": [{
"name": "Chun-MingChen",
"email": "nick830314@gmail.com",
"url": "https://github.com/Chun-MingChen"
}],
"license": "MIT",
"bugs": {
"url": "https://github.com/react-bootstrap-table/react-bootstrap-table2/issues"
},
"homepage": "https://github.com/react-bootstrap-table/react-bootstrap-table2#readme",
"devDependencies": {
"babel-core": "^6.25.0",
"babel-eslint": "^7.2.3",
"babel-jest": "^20.0.3",
"babel-loader": "^7.1.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.24.1",
"css-loader": "^0.28.1",
"enzyme": "^2.9.1",
"eslint": "^4.5.0",
"babel-cli": "6.26.0",
"babel-core": "6.25.0",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3",
"babel-loader": "7.1.1",
"babel-preset-es2015": "6.24.1",
"babel-preset-react": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"babel-register": "6.24.1",
"css-loader": "0.28.1",
"enzyme": "3.1.1",
"enzyme-adapter-react-16": "1.0.4",
"eslint": "4.5.0",
"eslint-config-airbnb": "15.1.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-import": "^2.7.0",
"eslint-loader": "1.9.0",
"eslint-plugin-import": "2.7.0",
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "^7.2.1",
"html-webpack-plugin": "^2.30.1",
"jest": "^20.0.4",
"jsdom": "^11.2.0",
"jsdom-global": "^3.0.2",
"lerna": "^2.0.0",
"node-sass": "^4.5.3",
"react-test-renderer": "^15.6.1",
"sass-loader": "^6.0.6",
"sinon": "^3.2.1",
"style-loader": "^0.17.0",
"webpack": "^3.5.4",
"webpack-dev-server": "^2.7.1"
"eslint-plugin-react": "7.2.1",
"gulp": "4.0.0",
"gulp-babel": "7.0.0",
"gulp-clean": "0.4.0",
"gulp-clean-css": "3.9.2",
"gulp-rename": "^1.2.2",
"gulp-sass": "3.1.0",
"gulp-shell": "0.6.5",
"html-webpack-plugin": "2.30.1",
"jest": "20.0.4",
"jsdom": "11.2.0",
"jsdom-global": "3.0.2",
"lerna": "2.0.0",
"node-sass": "4.5.3",
"react-test-renderer": "16.0.0",
"sass-loader": "6.0.6",
"sinon": "3.2.1",
"style-loader": "0.17.0",
"webpack": "3.5.4",
"webpack-dev-server": "2.7.1"
},
"dependencies": {
"classnames": "^2.2.5",
"prop-types": "^15.5.10",
"react": "^15.6.1",
"react-dom": "^15.6.1"
},
"peerDependencies": {
"prop-types": "^15.0.0",
"react": "^15.0.0",
"react-dom": "^15.0.0"
"classnames": "2.2.5",
"prop-types": "15.5.10",
"react": "16.0.0",
"react-dom": "16.0.0"
},
"jest": {
"collectCoverageFrom": [
@@ -71,6 +82,12 @@
"roots": [
"<rootDir>/packages"
],
"setupFiles": [
"<rootDir>/enzyme-setup.js"
],
"modulePaths": [
"<rootDir>/packages/react-bootstrap-table2"
],
"testEnvironment": "node",
"testMatch": [
"**/test/**/*.test.js"

View File

@@ -0,0 +1,59 @@
# react-bootstrap-table2-editor
`react-bootstrap-table2` separate the cell edit code base to [`react-bootstrap-table2-editor`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/develop/packages/react-bootstrap-table2-editor), so there's a little bit different when you use cell edit than `react-bootstrap-table`. In the following, we are going to show you how to enable the cell edit
**[Live Demo For Cell Edit](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Cell%20Editing)**
-----
## Install
```sh
$ npm install react-bootstrap-table2-editor --save
```
## How
We have [two ways](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/cell-edit-props.html#celleditmode-string) to trigger a editable cell as editing cell:
* click
* dbclick
That's look into how we enable the cell edit on tabe:
```js
import cellEditFactory from 'react-bootstrap-table2-editor';
// omit
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
```
How user save their new editings? We offer two ways:
* Press ENTER(**default**)
* Blur from current editing cell(Need to enable the [cellEdit.blurToSave](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/cell-edit-props.html#celleditblurtosave-bool))
## Editable Cell
`react-bootstrap-table2` support you to configure the cell editable on three level:
* Row Level ([cellEdit.nonEditableRows](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/cell-edit-props.html#celleditnoneditablerows-function))
* Column Level (Configure [column.editable](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditable-bool-function) as bool value)
* Cell Level (Configure [column.editable](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditable-bool-function) as a callback function)
## Customize Style/Class
Currently, we only support the editing cell style/class customization, in the future, we will offer more customizations.
### Editing Cell
* Customize the editing cell style via [column.editCellStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellstyle-object-function)
* Customize the editing cell classname via [column.editCellClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellclasses-string-function)
## Validation
[`column.validator`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnvalidator-function) will help you to work on it!

View File

@@ -0,0 +1,16 @@
import wrapperFactory from './src/wrapper';
import editingCellFactory from './src/editing-cell';
import {
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK
} from './src/const';
export default (options = {}) => ({
wrapperFactory,
editingCellFactory,
CLICK_TO_CELL_EDIT,
DBCLICK_TO_CELL_EDIT,
DELAY_FOR_DBCLICK,
options
});

View File

@@ -0,0 +1,42 @@
{
"name": "react-bootstrap-table2-editor",
"version": "0.0.3",
"description": "it's the editor addon for react-bootstrap-table2",
"main": "./lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/react-bootstrap-table/react-bootstrap-table2.git"
},
"keywords": [
"react",
"bootstrap",
"table",
"grid",
"react-bootstrap-table-addons",
"react-component"
],
"files": [
"lib/",
"dist/"
],
"tags": [
"react"
],
"author": "AllenFang",
"contributors": [
{
"name": "Chun-MingChen",
"email": "nick830314@gmail.com",
"url": "https://github.com/Chun-MingChen"
}
],
"peerDependencies": {
"prop-types": "^15.0.0",
"react": "^16.0.0",
"react-dom": "^16.0.0"
}
}

View File

@@ -0,0 +1,4 @@
export const TIME_TO_CLOSE_MESSAGE = 3000;
export const DELAY_FOR_DBCLICK = 200;
export const CLICK_TO_CELL_EDIT = 'click';
export const DBCLICK_TO_CELL_EDIT = 'dbclick';

View File

@@ -0,0 +1,153 @@
/* eslint react/prop-types: 0 */
/* eslint no-return-assign: 0 */
/* eslint class-methods-use-this: 0 */
/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
import React, { Component } from 'react';
import cs from 'classnames';
import PropTypes from 'prop-types';
import TextEditor from './text-editor';
import EditorIndicator from './editor-indicator';
import { TIME_TO_CLOSE_MESSAGE } from './const';
export default _ =>
class EditingCell extends Component {
static propTypes = {
row: PropTypes.object.isRequired,
column: PropTypes.object.isRequired,
onUpdate: PropTypes.func.isRequired,
onEscape: PropTypes.func.isRequired,
timeToCloseMessage: PropTypes.number,
className: PropTypes.string,
style: PropTypes.object
}
static defaultProps = {
timeToCloseMessage: TIME_TO_CLOSE_MESSAGE,
className: null,
style: {}
}
constructor(props) {
super(props);
this.indicatorTimer = null;
this.clearTimer = this.clearTimer.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.beforeComplete = this.beforeComplete.bind(this);
this.state = {
invalidMessage: null
};
}
componentWillReceiveProps({ message }) {
if (_.isDefined(message)) {
this.createTimer();
this.setState(() => ({
invalidMessage: message
}));
}
}
componentWillUnmount() {
this.clearTimer();
}
clearTimer() {
if (this.indicatorTimer) {
clearTimeout(this.indicatorTimer);
}
}
createTimer() {
this.clearTimer();
const { timeToCloseMessage, onErrorMessageDisappear } = this.props;
this.indicatorTimer = _.sleep(() => {
this.setState(() => ({
invalidMessage: null
}));
if (_.isFunction(onErrorMessageDisappear)) onErrorMessageDisappear();
}, timeToCloseMessage);
}
beforeComplete(row, column, newValue) {
const { onUpdate } = this.props;
if (_.isFunction(column.validator)) {
const validateForm = column.validator(newValue, row, column);
if (_.isObject(validateForm) && !validateForm.valid) {
this.setState(() => ({
invalidMessage: validateForm.message
}));
this.createTimer();
return;
}
}
onUpdate(row, column, newValue);
}
handleBlur() {
const { onEscape, blurToSave, row, column } = this.props;
if (blurToSave) {
const value = this.editor.text.value;
if (!_.isDefined(value)) {
// TODO: for other custom or embed editor
}
this.beforeComplete(row, column, value);
} else {
onEscape();
}
}
handleKeyDown(e) {
const { onEscape, row, column } = this.props;
if (e.keyCode === 27) { // ESC
onEscape();
} else if (e.keyCode === 13) { // ENTER
const value = e.currentTarget.value;
if (!_.isDefined(value)) {
// TODO: for other custom or embed editor
}
this.beforeComplete(row, column, value);
}
}
handleClick(e) {
if (e.target.tagName !== 'TD') {
// To avoid the row selection event be triggered,
// When user define selectRow.clickToSelect and selectRow.clickToEdit
// We shouldn't trigger selection event even if user click on the cell editor(input)
e.stopPropagation();
}
}
render() {
const { invalidMessage } = this.state;
const { row, column, className, style } = this.props;
const { dataField } = column;
const value = _.get(row, dataField);
const editorAttrs = {
onKeyDown: this.handleKeyDown,
onBlur: this.handleBlur
};
const hasError = _.isDefined(invalidMessage);
const editorClass = hasError ? cs('animated', 'shake') : null;
return (
<td
className={ cs('react-bootstrap-table-editing-cell', className) }
style={ style }
onClick={ this.handleClick }
>
<TextEditor
ref={ node => this.editor = node }
defaultValue={ value }
className={ editorClass }
{ ...editorAttrs }
/>
{ hasError ? <EditorIndicator invalidMessage={ invalidMessage } /> : null }
</td>
);
}
};

View File

@@ -11,8 +11,8 @@ class TextEditor extends Component {
}
render() {
const { defaultValue, classNames, ...rest } = this.props;
const editorClass = cs('form-control editor edit-text', classNames);
const { defaultValue, className, ...rest } = this.props;
const editorClass = cs('form-control editor edit-text', className);
return (
<input
ref={ node => this.text = node }
@@ -25,7 +25,7 @@ class TextEditor extends Component {
}
TextEditor.propTypes = {
classNames: PropTypes.oneOfType([
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object
]),
@@ -35,6 +35,6 @@ TextEditor.propTypes = {
]).isRequired
};
TextEditor.defaultProps = {
classNames: null
className: null
};
export default TextEditor;

View File

@@ -0,0 +1,135 @@
/* eslint react/prop-types: 0 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
export default (
Base,
{ _, remoteResolver }
) => {
let EditingCell;
return class CellEditWrapper extends remoteResolver(Component) {
static propTypes = {
options: PropTypes.shape({
mode: PropTypes.oneOf([CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT]).isRequired,
onErrorMessageDisappear: PropTypes.func,
blurToSave: PropTypes.bool,
beforeSaveCell: PropTypes.func,
afterSaveCell: PropTypes.func,
nonEditableRows: PropTypes.func,
timeToCloseMessage: PropTypes.number,
errorMessage: PropTypes.string
})
}
constructor(props) {
super(props);
EditingCell = props.cellEdit.editingCellFactory(_);
this.startEditing = this.startEditing.bind(this);
this.escapeEditing = this.escapeEditing.bind(this);
this.completeEditing = this.completeEditing.bind(this);
this.handleCellUpdate = this.handleCellUpdate.bind(this);
this.state = {
ridx: null,
cidx: null,
message: null,
isDataChanged: false
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.cellEdit && this.isRemoteCellEdit()) {
if (nextProps.cellEdit.options.errorMessage) {
this.setState(() => ({
isDataChanged: false,
message: nextProps.cellEdit.options.errorMessage
}));
} else {
this.setState(() => ({
isDataChanged: true
}));
this.escapeEditing();
}
} else {
this.setState(() => ({
isDataChanged: false
}));
}
}
handleCellUpdate(row, column, newValue) {
const { keyField, cellEdit, store } = this.props;
const { beforeSaveCell, afterSaveCell } = cellEdit.options;
const oldValue = _.get(row, column.dataField);
const rowId = _.get(row, keyField);
if (_.isFunction(beforeSaveCell)) beforeSaveCell(oldValue, newValue, row, column);
if (this.isRemoteCellEdit()) {
this.handleCellChange(rowId, column.dataField, newValue);
} else {
store.edit(rowId, column.dataField, newValue);
if (_.isFunction(afterSaveCell)) afterSaveCell(oldValue, newValue, row, column);
this.completeEditing();
}
}
completeEditing() {
this.setState(() => ({
ridx: null,
cidx: null,
message: null,
isDataChanged: true
}));
}
startEditing(ridx, cidx) {
const editing = () => {
this.setState(() => ({
ridx,
cidx,
isDataChanged: false
}));
};
const { selectRow } = this.props;
if (!selectRow || (selectRow.clickToEdit || !selectRow.clickToSelect)) editing();
}
escapeEditing() {
this.setState(() => ({
ridx: null,
cidx: null
}));
}
render() {
const { isDataChanged, ...stateRest } = this.state;
const {
cellEdit: {
options: { nonEditableRows, errorMessage, ...optionsRest },
editingCellFactory,
...cellEditRest
}
} = this.props;
const newCellEdit = {
...optionsRest,
...cellEditRest,
...stateRest,
EditingCell,
nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [],
onStart: this.startEditing,
onEscape: this.escapeEditing,
onUpdate: this.handleCellUpdate
};
return (
<Base
{ ...this.props }
data={ this.props.store.data }
isDataChanged={ isDataChanged }
cellEdit={ newCellEdit }
/>
);
}
};
};

View File

@@ -1,17 +1,28 @@
/* eslint react/prop-types: 0 */
import 'jsdom-global/register';
import React from 'react';
import sinon from 'sinon';
import { shallow, mount } from 'enzyme';
import { TableRowWrapper } from './test-helpers/table-wrapper';
import EditingCell from '../src/editing-cell';
import _ from 'react-bootstrap-table-next/src/utils';
import editingCellFactory from '../src/editing-cell';
import TextEditor from '../src/text-editor';
import EditorIndicator from '../src/editor-indicator';
const EditingCell = editingCellFactory(_);
const TableRowWrapper = props => (
<table>
<tbody>
<tr>{ props.children }</tr>
</tbody>
</table>
);
describe('EditingCell', () => {
let wrapper;
let onUpdate;
let onEscape;
let onComplete;
const row = {
id: 1,
name: 'A'
@@ -23,14 +34,14 @@ describe('EditingCell', () => {
};
beforeEach(() => {
onComplete = sinon.stub();
onEscape = sinon.stub();
onUpdate = sinon.stub();
wrapper = shallow(
<EditingCell
row={ row }
column={ column }
onUpdate={ onUpdate }
onEscape={ onEscape }
onComplete={ onComplete }
/>
);
});
@@ -47,7 +58,7 @@ describe('EditingCell', () => {
expect(textEditor.props().defaultValue).toEqual(row[column.dataField]);
expect(textEditor.props().onKeyDown).toBeDefined();
expect(textEditor.props().onBlur).toBeDefined();
expect(textEditor.props().classNames).toBeNull();
expect(textEditor.props().className).toBeNull();
});
it('should not render EditorIndicator due to state.invalidMessage is null', () => {
@@ -55,12 +66,12 @@ describe('EditingCell', () => {
expect(indicator.length).toEqual(0);
});
it('when press ENTER on TextEditor should call onComplete correctly', () => {
it('when press ENTER on TextEditor should call onUpdate correctly', () => {
const newValue = 'test';
const textEditor = wrapper.find(TextEditor);
textEditor.simulate('keyDown', { keyCode: 13, currentTarget: { value: newValue } });
expect(onComplete.callCount).toBe(1);
expect(onComplete.calledWith(row, column, newValue)).toBe(true);
expect(onUpdate.callCount).toBe(1);
expect(onUpdate.calledWith(row, column, newValue)).toBe(true);
});
it('when press ESC on TextEditor should call onEscape correctly', () => {
@@ -75,6 +86,46 @@ describe('EditingCell', () => {
expect(onEscape.callCount).toBe(1);
});
describe('if style prop is defined', () => {
const customStyle = { backgroundColor: 'red' };
beforeEach(() => {
wrapper = shallow(
<EditingCell
row={ row }
column={ column }
onUpdate={ onUpdate }
onEscape={ onEscape }
style={ customStyle }
/>
);
});
it('should render component with style successfully', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find('td').prop('style')).toEqual(customStyle);
});
});
describe('if className prop is defined', () => {
const className = 'test-class';
beforeEach(() => {
wrapper = shallow(
<EditingCell
row={ row }
column={ column }
onUpdate={ onUpdate }
onEscape={ onEscape }
className={ className }
/>
);
});
it('should render component with style successfully', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.hasClass(className)).toBe(true);
});
});
describe('if blurToSave prop is true', () => {
beforeEach(() => {
wrapper = mount(
@@ -82,19 +133,19 @@ describe('EditingCell', () => {
<EditingCell
row={ row }
column={ column }
onUpdate={ onUpdate }
onEscape={ onEscape }
onComplete={ onComplete }
blurToSave
/>
</TableRowWrapper>
);
});
it('when blur from TextEditor should call onComplete correctly', () => {
it('when blur from TextEditor should call onUpdate correctly', () => {
const textEditor = wrapper.find(TextEditor);
textEditor.simulate('blur');
expect(onComplete.callCount).toBe(1);
expect(onComplete.calledWith(row, column, `${row[column.dataField]}`)).toBe(true);
expect(onUpdate.callCount).toBe(1);
expect(onUpdate.calledWith(row, column, `${row[column.dataField]}`)).toBe(true);
});
});
@@ -113,6 +164,14 @@ describe('EditingCell', () => {
text: 'ID',
validator: validatorCallBack
};
wrapper = mount(
<EditingCell
row={ row }
column={ column }
onUpdate={ onUpdate }
onEscape={ onEscape }
/>
);
wrapper.instance().beforeComplete(row, column, newValue);
});
@@ -121,8 +180,8 @@ describe('EditingCell', () => {
expect(validatorCallBack.calledWith(newValue, row, column)).toBe(true);
});
it('should not call onComplete', () => {
expect(onComplete.callCount).toBe(0);
it('should not call onUpdate', () => {
expect(onUpdate.callCount).toBe(0);
});
it('should set indicatorTimer successfully', () => {
@@ -135,11 +194,14 @@ describe('EditingCell', () => {
it('should render TextEditor with correct shake and animated class', () => {
const editor = wrapper.find(TextEditor);
expect(editor.length).toEqual(1);
expect(editor.props().classNames).toEqual('animated shake');
expect(editor.html()).toEqual('<input type="text" class="form-control editor edit-text animated shake">');
/* Following is better, but it will not work after upgrade React to 16 and enzyme... */
// expect(editor.length).toEqual(1);
// expect(editor.props().classNames).toEqual('animated shake');
});
it('should render EditorIndicator correctly', () => {
/* Following is better, but it will not work after upgrade React to 16 and enzyme... */
xit('should render EditorIndicator correctly', () => {
const indicator = wrapper.find(EditorIndicator);
expect(indicator.length).toEqual(1);
expect(indicator.props().invalidMessage).toEqual(validForm.message);
@@ -164,8 +226,8 @@ describe('EditingCell', () => {
expect(validatorCallBack.calledWith(newValue, row, column)).toBe(true);
});
it('should call onComplete', () => {
expect(onComplete.callCount).toBe(1);
it('should call onUpdate', () => {
expect(onUpdate.callCount).toBe(1);
});
});
});

View File

@@ -1,5 +1,6 @@
import 'jsdom-global/register';
import React from 'react';
import { shallow } from 'enzyme';
import { mount } from 'enzyme';
import TextEditor from '../src/text-editor';
@@ -8,7 +9,7 @@ describe('TextEditor', () => {
const value = 'test';
beforeEach(() => {
wrapper = shallow(
wrapper = mount(
<TextEditor
defaultValue={ value }
/>
@@ -22,20 +23,20 @@ describe('TextEditor', () => {
expect(wrapper.find('.form-control.editor.edit-text').length).toBe(1);
});
describe('whenclassNames prop defined', () => {
describe('when className prop defined', () => {
const className = 'test-class';
beforeEach(() => {
wrapper = shallow(
wrapper = mount(
<TextEditor
defaultValue={ value }
classNames={ className }
className={ className }
/>
);
});
it('should render correct custom classname', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find(`.${className}`).length).toBe(1);
expect(wrapper.hasClass(className)).toBeTruthy();
});
});
});

View File

@@ -0,0 +1,330 @@
import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
import _ from 'react-bootstrap-table-next/src/utils';
import remoteResolver from 'react-bootstrap-table-next/src/props-resolver/remote-resolver';
import Store from 'react-bootstrap-table-next/src/store';
import BootstrapTable from 'react-bootstrap-table-next/src/bootstrap-table';
import cellEditFactory from '..';
import * as Const from '../src/const';
import wrapperFactory from '../src/wrapper';
describe('CellEditWrapper', () => {
let wrapper;
let instance;
const onTableChangeCB = sinon.stub();
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const data = [{
id: 1,
name: 'A'
}, {
id: 2,
name: 'B'
}];
const createTableProps = (props = {}) => {
const { cellEdit, ...rest } = props;
const tableProps = {
keyField: 'id',
columns,
data,
_,
store: new Store('id'),
cellEdit: cellEditFactory(cellEdit),
onTableChange: onTableChangeCB,
...rest
};
tableProps.store.data = data;
return tableProps;
};
const CellEditWrapper = wrapperFactory(BootstrapTable, {
_,
remoteResolver
});
const createCellEditWrapper = (props, renderFragment = true) => {
wrapper = shallow(<CellEditWrapper { ...props } />);
instance = wrapper.instance();
if (renderFragment) {
const fragment = instance.render();
wrapper = shallow(<div>{ fragment }</div>);
}
};
afterEach(() => {
onTableChangeCB.reset();
});
beforeEach(() => {
const props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT }
});
createCellEditWrapper(props);
});
it('should render CellEditWrapper correctly', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find(BootstrapTable)).toBeDefined();
});
it('should have correct state', () => {
expect(instance.state.ridx).toBeNull();
expect(instance.state.cidx).toBeNull();
expect(instance.state.message).toBeNull();
expect(instance.state.isDataChanged).toBeFalsy();
});
it('should inject correct props to base component', () => {
const base = wrapper.find(BootstrapTable);
expect(base.props().cellEdit).toBeDefined();
expect(base.props().cellEdit.onStart).toBeDefined();
expect(base.props().cellEdit.onEscape).toBeDefined();
expect(base.props().cellEdit.onUpdate).toBeDefined();
expect(base.props().cellEdit.EditingCell).toBeDefined();
expect(base.props().cellEdit.ridx).toBeNull();
expect(base.props().cellEdit.cidx).toBeNull();
expect(base.props().cellEdit.message).toBeNull();
expect(base.props().isDataChanged).toBe(instance.state.isDataChanged);
});
describe('when receive new cellEdit prop', () => {
const spy = jest.spyOn(CellEditWrapper.prototype, 'escapeEditing');
describe('and cellEdit is not work on remote', () => {
beforeEach(() => {
const props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT }
});
createCellEditWrapper(props);
wrapper.setProps({ cellEdit: props.cellEdit });
});
it('should always setting state.isDataChanged as false', () => {
expect(instance.state.isDataChanged).toBeFalsy();
});
});
describe('and cellEdit is work on remote', () => {
let errorMessage;
let props;
beforeEach(() => {
props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT },
remote: true
});
});
describe('and cellEdit.errorMessage is defined', () => {
beforeEach(() => {
createCellEditWrapper(props, false);
errorMessage = 'test';
const newCellEdit = {
...props.cellEdit,
options: { ...props.cellEdit.options, errorMessage }
};
wrapper.setProps({ cellEdit: newCellEdit });
});
it('should setting correct state', () => {
expect(instance.state.isDataChanged).toBeFalsy();
expect(instance.state.message).toEqual(errorMessage);
});
});
describe('and cellEdit.errorMessage is undefined', () => {
beforeEach(() => {
errorMessage = null;
createCellEditWrapper(props, false);
const newCellEdit = {
...props.cellEdit,
options: { ...props.cellEdit.options, errorMessage }
};
wrapper.setProps({ cellEdit: newCellEdit });
});
it('should setting correct state', () => {
expect(wrapper.state().isDataChanged).toBeTruthy();
});
it('should escape current editing', () => {
expect(spy).toHaveBeenCalled();
});
});
});
});
describe('call escapeEditing function', () => {
it('should set state correctly', () => {
instance.escapeEditing();
expect(instance.state.ridx).toBeNull();
expect(instance.state.cidx).toBeNull();
});
});
describe('call startEditing function', () => {
const ridx = 1;
const cidx = 3;
it('should set state correctly', () => {
instance.startEditing(ridx, cidx);
expect(instance.state.ridx).toEqual(ridx);
expect(instance.state.cidx).toEqual(cidx);
expect(instance.state.isDataChanged).toBeFalsy();
});
describe('if selectRow.clickToSelect is defined', () => {
beforeEach(() => {
const selectRow = { mode: 'checkbox', clickToSelect: true };
const props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT },
selectRow
});
createCellEditWrapper(props);
});
it('should not set state', () => {
instance.startEditing(ridx, cidx);
expect(instance.state.ridx).toBeNull();
expect(instance.state.cidx).toBeDefined();
});
});
describe('if selectRow.clickToSelect and selectRow.clickToEdit is defined', () => {
beforeEach(() => {
const selectRow = { mode: 'checkbox', clickToSelect: true, clickToEdit: true };
const props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT },
selectRow
});
createCellEditWrapper(props);
});
it('should set state correctly', () => {
instance.startEditing(ridx, cidx);
expect(instance.state.ridx).toEqual(ridx);
expect(instance.state.cidx).toEqual(cidx);
});
});
});
describe('call completeEditing function', () => {
it('should set state correctly', () => {
instance.completeEditing();
expect(instance.state.ridx).toBeNull();
expect(instance.state.cidx).toBeNull();
expect(instance.state.message).toBeNull();
expect(instance.state.isDataChanged).toBeTruthy();
});
});
describe('call handleCellUpdate function', () => {
let props;
const row = data[0];
const column = columns[1];
const newValue = 'new name';
describe('when cell edit is work on remote', () => {
const spy = jest.spyOn(CellEditWrapper.prototype, 'handleCellChange');
beforeEach(() => {
props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT },
remote: true
});
createCellEditWrapper(props);
instance.handleCellUpdate(row, column, newValue);
});
it('should calling handleCellChange correctly', () => {
expect(spy).toHaveBeenCalled();
expect(spy.mock.calls).toHaveLength(1);
expect(spy.mock.calls[0]).toHaveLength(3);
expect(spy.mock.calls[0][0]).toEqual(row.id);
expect(spy.mock.calls[0][1]).toEqual(column.dataField);
expect(spy.mock.calls[0][2]).toEqual(newValue);
});
});
describe('when cell edit is not work on remote', () => {
const spyOnCompleteEditing = jest.spyOn(CellEditWrapper.prototype, 'completeEditing');
const spyOnStoreEdit = jest.spyOn(Store.prototype, 'edit');
beforeEach(() => {
props = createTableProps({
cellEdit: { mode: Const.CLICK_TO_CELL_EDIT }
});
createCellEditWrapper(props);
instance.handleCellUpdate(row, column, newValue);
});
afterEach(() => {
spyOnStoreEdit.mockReset();
spyOnCompleteEditing.mockReset();
});
it('should calling props.store.edit', () => {
expect(spyOnStoreEdit).toHaveBeenCalled();
expect(spyOnStoreEdit.mock.calls).toHaveLength(1);
expect(spyOnStoreEdit.mock.calls[0]).toHaveLength(3);
expect(spyOnStoreEdit.mock.calls[0][0]).toEqual(row.id);
expect(spyOnStoreEdit.mock.calls[0][1]).toEqual(column.dataField);
expect(spyOnStoreEdit.mock.calls[0][2]).toEqual(newValue);
});
it('should calling completeEditing function', () => {
expect(spyOnCompleteEditing).toHaveBeenCalled();
});
describe('if cellEdit.afterSaveCell prop defined', () => {
const aftereSaveCellCallBack = sinon.stub();
beforeEach(() => {
props = createTableProps({
cellEdit: {
mode: Const.CLICK_TO_CELL_EDIT,
afterSaveCell: aftereSaveCellCallBack
}
});
createCellEditWrapper(props);
instance.handleCellUpdate(row, column, newValue);
});
it('should calling cellEdit.afterSaveCell correctly', () => {
expect(aftereSaveCellCallBack.callCount).toBe(1);
expect(aftereSaveCellCallBack.calledWith(
row[column.dataField], newValue, row, column)
).toBe(true);
});
});
});
describe('if cellEdit.beforeSaveCell prop defined', () => {
const beforeSaveCellCallBack = sinon.stub();
beforeEach(() => {
props = createTableProps({
cellEdit: {
mode: Const.CLICK_TO_CELL_EDIT,
beforeSaveCell: beforeSaveCellCallBack
}
});
createCellEditWrapper(props);
instance.handleCellUpdate(row, column, newValue);
});
it('should calling cellEdit.beforeSaveCell correctly', () => {
expect(beforeSaveCellCallBack.callCount).toBe(1);
expect(beforeSaveCellCallBack.calledWith(
row[column.dataField], newValue, row, column)
).toBe(true);
});
});
});
});

View File

@@ -0,0 +1,3 @@
{
"presets": ["react", "es2015", "stage-0", ["env", {"modules": false} ]]
}

View File

@@ -2,3 +2,4 @@
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import '@storybook/addon-console';

View File

@@ -1,6 +1,7 @@
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions */
import React from 'react';
import { configure, addDecorator } from '@storybook/react';
import { withConsole } from '@storybook/addon-console';
function loadStories() {
require('stories');
@@ -16,6 +17,10 @@ const componentDecorator = (story) => (
</div>
);
// prepend the story name to log messages
addDecorator((storyFn, context) => withConsole()(storyFn)(context));
addDecorator(componentDecorator);
configure(loadStories, module);

View File

@@ -1,7 +1,12 @@
const path = require('path');
const sourcePath = path.join(__dirname, '../../react-bootstrap-table2/src');
const sourcePath = path.join(__dirname, '../../react-bootstrap-table2');
const paginationSourcePath = path.join(__dirname, '../../react-bootstrap-table2-paginator');
const overlaySourcePath = path.join(__dirname, '../../react-bootstrap-table2-overlay');
const filterSourcePath = path.join(__dirname, '../../react-bootstrap-table2-filter');
const editorSourcePath = path.join(__dirname, '../../react-bootstrap-table2-editor');
const sourceStylePath = path.join(__dirname, '../../react-bootstrap-table2/style');
const paginationStylePath = path.join(__dirname, '../../react-bootstrap-table2-paginator/style');
const storyPath = path.join(__dirname, '../stories');
const examplesPath = path.join(__dirname, '../examples');
const srcPath = path.join(__dirname, '../src');
@@ -11,6 +16,12 @@ const aliasPath = {
src: srcPath,
components: path.join(srcPath, 'components'),
utils: path.join(srcPath, 'utils'),
'react-bootstrap-table-next': sourcePath,
'react-bootstrap-table2-editor': editorSourcePath,
'react-bootstrap-table2-filter': filterSourcePath,
'react-bootstrap-table2-overlay': overlaySourcePath,
'react-bootstrap-table2-paginator': paginationSourcePath,
};
const loaders = [{
@@ -23,14 +34,14 @@ const loaders = [{
test: /\.js?$/,
use: ['babel-loader'],
exclude: /node_modules/,
include: [sourcePath, storyPath],
include: [sourcePath, paginationSourcePath, overlaySourcePath, filterSourcePath, editorSourcePath, storyPath]
}, {
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}, {
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: [storyPath, sourceStylePath],
include: [storyPath, sourceStylePath, paginationStylePath],
}, {
test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000',

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -18,7 +18,7 @@ const columns = [{
}];
const sourceCode = `\
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
@@ -28,7 +28,7 @@ const sourceCode = `\
export default () => (
<div>
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -31,17 +31,17 @@ const columns = [{
const CaptionElement = () => <h3 style={{ borderRadius: '0.25em', textAlign: 'center', color: 'purple', border: '1px solid purple', padding: '0.5em' }}>Component as Header</h3>;
<BootstrapTableful keyField="id" data={ products } caption="Plain text header" columns={ columns } />
<BootstrapTable keyField="id" data={ products } caption="Plain text header" columns={ columns } />
<BootstrapTableful keyField="id" data={ products } caption={<CaptionElement />} columns={ columns } />
<BootstrapTable keyField="id" data={ products } caption={<CaptionElement />} columns={ columns } />
`;
const Caption = () => <h3 style={{ borderRadius: '0.25em', textAlign: 'center', color: 'purple', border: '1px solid purple', padding: '0.5em' }}>Component as Header</h3>;
const Caption = () => <h3 style={ { borderRadius: '0.25em', textAlign: 'center', color: 'purple', border: '1px solid purple', padding: '0.5em' } }>Component as Header</h3>;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } caption="Plain text header" columns={ columns } />
<BootstrapTableful keyField="id" data={ products } caption={<Caption />} columns={ columns } />
<BootstrapTable keyField="id" data={ products } caption="Plain text header" columns={ columns } />
<BootstrapTable keyField="id" data={ products } caption={ <Caption /> } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -29,12 +29,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
const columns = [{
@@ -15,7 +15,7 @@ const columns = [{
}];
const sourceCode = `\
<BootstrapTableful keyField='id' data={ [] } columns={ columns } noDataIndication="Table is Empty" />
<BootstrapTable keyField='id' data={ [] } columns={ columns } noDataIndication="Table is Empty" />
// Following is more customizable example
@@ -23,12 +23,12 @@ function indication() {
// return something here
}
<BootstrapTableful keyField='id' data={ [] } columns={ columns } noDataIndication={ indication } />
<BootstrapTable keyField='id' data={ [] } columns={ columns } noDataIndication={ indication } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ [] } columns={ columns } noDataIndication="Table is Empty" />
<BootstrapTable keyField="id" data={ [] } columns={ columns } noDataIndication="Table is Empty" />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -18,7 +18,7 @@ const columns = [{
}];
const sourceCode = `\
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
@@ -30,7 +30,7 @@ const sourceCode = `\
export default () => (
<div>
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -18,6 +19,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -29,26 +32,28 @@ const columns = [{
text: 'Product Price'
}];
const cellEdit = {
mode: 'click',
blurToSave: true
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true
}) }
/>
`;
const cellEdit = {
mode: 'click',
blurToSave: true
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true
}) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,60 @@
/* 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',
editCellClasses: 'editing-name'
}, {
dataField: 'price',
text: 'Product Price',
editCellClasses: (cell, row, rowIndex, colIndex) =>
(cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101')
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
editCellClasses: 'editing-name'
}, {
dataField: 'price',
text: 'Product Price',
editCellClasses: (cell, row, rowIndex, colIndex) =>
(cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101')
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
`;
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -2,7 +2,8 @@
/* eslint no-console: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -20,6 +21,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -31,28 +34,30 @@ const columns = [{
text: 'Product Price'
}];
const cellEdit = {
mode: 'click',
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({
mode: 'click',
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
}) }
/>
`;
const cellEdit = {
mode: 'click',
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({
mode: 'click',
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
}) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,68 @@
/* 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',
editCellStyle: {
backgroundColor: '#20B2AA'
}
}, {
dataField: 'price',
text: 'Product Price',
editCellStyle: (cell, row, rowIndex, colIndex) => {
const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF';
return { backgroundColor };
}
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
editCellStyle: {
backgroundColor: '#20B2AA'
}
}, {
dataField: 'price',
text: 'Product Price',
editCellStyle: (cell, row, rowIndex, colIndex) => {
const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF';
return { backgroundColor };
}
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
`;
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,7 @@
import React from 'react';
/* eslint no-unused-vars: 0 */
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -33,6 +34,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -59,27 +62,29 @@ const columns = [{
}
}];
const cellEdit = {
mode: 'click',
blurToSave: true
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true
}) }
/>
`;
const cellEdit = {
mode: 'click',
blurToSave: true
};
export default () => (
<div>
<h3>Product Price should bigger than $2000</h3>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true
}) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,8 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -20,6 +21,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -32,24 +35,22 @@ const columns = [{
editable: (content, row, rowIndex, columnIndex) => content > 2101
}];
const cellEdit = {
mode: 'click'
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
`;
const cellEdit = {
mode: 'click'
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,8 @@
/* eslint react/prefer-stateless-function: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -18,6 +20,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -29,24 +33,22 @@ const columns = [{
text: 'Product Price'
}];
const cellEdit = {
mode: 'click'
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
`;
const cellEdit = {
mode: 'click'
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -19,6 +20,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -32,26 +35,28 @@ const columns = [{
text: 'Product Price'
}];
const cellEdit = {
mode: 'click',
blurToSave: true
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true
}) }
/>
`;
const cellEdit = {
mode: 'click',
blurToSave: true
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true
}) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -18,6 +19,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -29,24 +32,22 @@ const columns = [{
text: 'Product Price'
}];
const cellEdit = {
mode: 'dbclick'
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({ mode: 'dbclick' }) }
/>
`;
const cellEdit = {
mode: 'dbclick'
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'dbclick' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
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';
@@ -18,6 +19,8 @@ const columns = [{
}];
const sourceCode = `\
import cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const columns = [{
dataField: 'id',
text: 'Product ID'
@@ -29,29 +32,29 @@ const columns = [{
text: 'Product Price'
}];
const cellEdit = {
mode: 'click',
blurToSave: true,
// Product ID: 0, 3 will be non-editable
nonEditableRows: () => [0, 3]
};
<BootstrapTableful
keyField='id'
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEdit }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true,
nonEditableRows: () => [0, 3]
}) }
/>
`;
const cellEdit = {
mode: 'click',
blurToSave: true,
nonEditableRows: () => [0, 3]
};
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } cellEdit={ cellEdit } />
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
cellEdit={ cellEditFactory({
mode: 'click',
blurToSave: true,
nonEditableRows: () => [0, 3]
}) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,74 @@
/* eslint no-unused-vars: 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 { jobsGenerator } from 'utils/common';
const jobs = jobsGenerator(5);
const owners = ['Allen', 'Bob', 'Cat'];
const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money'];
const columns = [{
dataField: 'id',
text: 'Job ID'
}, {
dataField: 'name',
text: 'Job Name',
filter: textFilter()
}, {
dataField: 'owner',
text: 'Job Owner',
filter: textFilter(),
formatter: (cell, row) => owners[cell],
filterValue: (cell, row) => owners[cell]
}, {
dataField: 'type',
text: 'Job Type',
filter: textFilter(),
formatter: (cell, row) => types[cell],
filterValue: (cell, row) => types[cell]
}];
const sourceCode = `\
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
const owners = ['Allen', 'Bob', 'Cat'];
const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money'];
const columns = [{
dataField: 'id',
text: 'Job ID'
}, {
dataField: 'name',
text: 'Job Name',
filter: textFilter()
}, {
dataField: 'owner',
text: 'Job Owner',
filter: textFilter(),
formatter: (cell, row) => owners[cell],
filterValue: (cell, row) => owners[cell]
}, {
dataField: 'type',
text: 'Job Type',
filter: textFilter(),
filterValue: (cell, row) => types[cell]
}];
// shape of job: { id: 0, name: 'Job name 0', owner: 1, type: 3 }
<BootstrapTable keyField='id' data={ jobs } columns={ columns } filter={ filterFactory() } />
`;
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ jobs }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,68 @@
/* 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({
delay: 1000, // default is 500ms
style: {
backgroundColor: 'yellow'
},
className: 'test-classname',
placeholder: 'Custom PlaceHolder',
onClick: e => console.log(e)
})
}];
const sourceCode = `\
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({
delay: 1000, // default is 500ms
style: {
backgroundColor: 'yellow'
},
className: 'test-classname',
placeholder: 'Custom PlaceHolder',
onClick: e => console.log(e)
})
}];
<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,55 @@
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({
defaultValue: '2103'
})
}];
const sourceCode = `\
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({
defaultValue: '2103'
})
}];
<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,56 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter, Comparator } 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({
comparator: Comparator.EQ // default is Comparator.LIKE
})
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}];
const sourceCode = `\
import filterFactory, { textFilter, Comparator } from 'react-bootstrap-table2-filter';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter({
comparator: Comparator.EQ
})
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
`;
export default () => (
<div>
<h3>Product Name filter apply Equal Comparator</h3>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,51 @@
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()
}];
const sourceCode = `\
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()
}];
<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

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -40,12 +40,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -34,12 +34,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -40,12 +40,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -2,7 +2,7 @@
/* eslint no-alert: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -37,13 +37,13 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<h3>Try to Click on Product ID columns</h3>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -53,7 +53,7 @@ const columns = [
formatter: priceFormatter
}];
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
@@ -62,7 +62,7 @@ const columns = [
export default () => (
<div>
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }

View File

@@ -1,7 +1,7 @@
/* eslint no-console: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -51,7 +51,7 @@ const columns = [
down: 'glyphicon glyphicon-chevron-down'
}];
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
@@ -60,7 +60,7 @@ const columns = [
export default () => (
<div>
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -28,12 +28,12 @@ const columns = [{
// omit...
];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -58,12 +58,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -34,12 +34,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -49,12 +49,12 @@ const columns = [{
text: 'PostCode'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -34,12 +34,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -34,12 +34,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -40,12 +40,12 @@ const columns = [{
}
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -2,7 +2,7 @@
/* eslint no-alert: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -37,13 +37,13 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<h3>Try to Click on Product ID header column</h3>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,90 @@
/* eslint no-unused-vars: 0 */
/* eslint react/prefer-stateless-function: 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();
function priceFormatter(column, colIndex, { sortElement, filterElement }) {
return (
<div style={ { display: 'flex', flexDirection: 'column' } }>
{ filterElement }
{ column.text }
{ sortElement }
</div>
);
}
const columns = [{
dataField: 'id',
text: 'Product ID',
sort: true
}, {
dataField: 'name',
text: 'Product Name',
sort: true
}, {
dataField: 'price',
text: 'Product Price',
sort: true,
filter: textFilter(),
headerFormatter: priceFormatter
}];
const defaultSorted = [{
dataField: 'name',
order: 'desc'
}];
const sourceCode = `\
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
// ...
function priceFormatter(column, colIndex, { sortElement, filterElement }) {
return (
<div style={ { display: 'flex', flexDirection: 'column' } }>
{ filterElement }
{ column.text }
{ sortElement }
</div>
);
}
const columns = [
// omit...
{
dataField: 'price',
text: 'Product Price',
sort: true,
filter: textFilter(),
headerFormatter: priceFormatter
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
defaultSorted={ defaultSorted }
/>
`;
export default class DefaultSortTable extends React.PureComponent {
render() {
return (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
defaultSorted={ defaultSorted }
/>
<Code>{ sourceCode }</Code>
</div>
);
}
}

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -40,7 +40,7 @@ const columns = [
headerFormatter: priceFormatter
}];
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
@@ -49,7 +49,7 @@ const columns = [
export default () => (
<div>
<BootstrapTableful
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -56,12 +56,12 @@ const columns = [{
}
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,7 +1,7 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -34,12 +34,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,145 @@
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import PropTypes from 'prop-types';
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 RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<BootstrapTable
remote
keyField="id"
data={ data }
columns={ columns }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1,
data: products.slice(0, 10),
sizePerPage: 10
};
}
handleTableChange = ({ 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 NoDataIndication = () => (
<div className="spinner">
<div className="rect1" />
<div className="rect2" />
<div className="rect3" />
<div className="rect4" />
<div className="rect5" />
</div>
);
const Table = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<BootstrapTable
remote
keyField="id"
data={ data }
columns={ columns }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
noDataIndication={ () => <NoDataIndication /> }
/>
<Code>{ sourceCode }</Code>
</div>
);
Table.propTypes = {
data: PropTypes.array.isRequired,
page: PropTypes.number.isRequired,
totalSize: PropTypes.number.isRequired,
sizePerPage: PropTypes.number.isRequired,
onTableChange: PropTypes.func.isRequired
};
class EmptyTableOverlay 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
}));
}, 3000);
this.setState(() => ({ data: [] }));
}
render() {
const { data, sizePerPage, page } = this.state;
return (
<Table
data={ data }
page={ page }
sizePerPage={ sizePerPage }
totalSize={ products.length }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default EmptyTableOverlay;

View File

@@ -0,0 +1,158 @@
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
import overlayFactory from 'react-bootstrap-table2-overlay';
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';
import overlayFactory from 'react-bootstrap-table2-overlay';
// ...
const RemotePagination = ({ loading, data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<BootstrapTable
remote
loading={ loading }
keyField="id"
data={ data }
columns={ columns }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);
RemotePagination.propTypes = {
data: PropTypes.array.isRequired,
page: PropTypes.number.isRequired,
loading: PropTypes.bool.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,
loading: false,
data: products.slice(0, 10),
sizePerPage: 10
};
}
handleTableChange = ({ page, sizePerPage }) => {
const currentIndex = (page - 1) * sizePerPage;
setTimeout(() => {
this.setState(() => ({
page,
loading: false,
data: products.slice(currentIndex, currentIndex + sizePerPage),
sizePerPage
}));
}, 3000);
this.setState(() => ({ loading: true }));
}
render() {
const { data, sizePerPage, page, loading } = this.state;
return (
<RemotePagination
data={ data }
page={ page }
loading={ loading }
sizePerPage={ sizePerPage }
totalSize={ products.length }
onTableChange={ this.handleTableChange }
/>
);
}
}
`;
const RemotePagination = ({ loading, data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<BootstrapTable
remote
loading={ loading }
keyField="id"
data={ data }
columns={ columns }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) }
/>
<Code>{ sourceCode }</Code>
</div>
);
RemotePagination.propTypes = {
data: PropTypes.array.isRequired,
page: PropTypes.number.isRequired,
loading: PropTypes.bool.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,
loading: false,
data: products.slice(0, 10),
sizePerPage: 10
};
}
handleTableChange = (type, { page, sizePerPage }) => {
const currentIndex = (page - 1) * sizePerPage;
setTimeout(() => {
this.setState(() => ({
page,
loading: false,
data: products.slice(currentIndex, currentIndex + sizePerPage),
sizePerPage
}));
}, 3000);
this.setState(() => ({ loading: true }));
}
render() {
const { data, sizePerPage, page, loading } = this.state;
return (
<RemotePagination
data={ data }
page={ page }
loading={ loading }
sizePerPage={ sizePerPage }
totalSize={ products.length }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View File

@@ -0,0 +1,82 @@
/* eslint react/prefer-stateless-function: 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 options = {
paginationSize: 4,
pageStartIndex: 0,
// alwaysShowAllBtns: true, // Always show next and previous button
// withFirstAndLast: false, // Hide the going to First and Last page button
// hideSizePerPage: true, // Hide the sizePerPage dropdown always
// hidePageListOnlyOnePage: true, // Hide the pagination list when only one page
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
sizePerPageList: [{
text: '5', value: 5
}, {
text: '10', value: 10
}, {
text: 'All', value: products.length
}] // A numeric array is also available. the purpose of above example is custom the text
};
<BootstrapTable keyField='id' data={ products } columns={ columns } pagination={ paginationFactory(options) } />
`;
const options = {
paginationSize: 4,
pageStartIndex: 0,
// alwaysShowAllBtns: true // Always show next and previous button
// withFirstAndLast: false // Hide the going to First and Last page button
// hideSizePerPage: true, // Hide the sizePerPage dropdown always
// hidePageListOnlyOnePage: true, // Hide the pagination list when only one page
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
sizePerPageList: [{
text: '5', value: 5
}, {
text: '10', value: 10
}, {
text: 'All', value: products.length
}] // A numeric array is also available. the purpose of above example is custom the text
};
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory(options) } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,45 @@
/* eslint react/prefer-stateless-function: 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 columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } pagination={ paginationFactory() } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } pagination={ paginationFactory() } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,82 @@
/* eslint react/prefer-stateless-function: 0 */
/* eslint no-console: 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 columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const options = {
onSizePerPageChange: (sizePerPage, page) => {
console.log('Size per page change!!!');
console.log('Newest size per page:' + sizePerPage);
console.log('Newest page:' + page);
},
onPageChange: (page, sizePerPage) => {
console.log('Page change!!!');
console.log('Newest size per page:' + sizePerPage);
console.log('Newest page:' + page);
}
};
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
pagination={ paginationFactory(options) }
/>
`;
const options = {
onSizePerPageChange: (sizePerPage, page) => {
console.log('Size per page change!!!');
console.log(`Newest size per page: ${sizePerPage}`);
console.log(`Newest page: ${page}`);
},
onPageChange: (page, sizePerPage) => {
console.log('Page change!!!');
console.log(`Newest size per page: ${sizePerPage}`);
console.log(`Newest page: ${page}`);
}
};
export default () => (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
pagination={ paginationFactory(options) }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,202 @@
/* eslint guard-for-in: 0 */
/* eslint no-restricted-syntax: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter, Comparator } from 'react-bootstrap-table2-filter';
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',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter, Comparator } 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()
}];
const RemoteAll = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<BootstrapTable
remote={ { pagination: true } }
keyField="id"
data={ data }
columns={ columns }
filter={ filterFactory() }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
RemoteAll.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),
totalSize: products.length,
sizePerPage: 10
};
this.handleTableChange = this.handleTableChange.bind(this);
}
handleTableChange = (type, { page, sizePerPage, filters }) => {
const currentIndex = (page - 1) * sizePerPage;
setTimeout(() => {
const result = products.filter((row) => {
let valid = true;
for (const dataField in filters) {
const { filterVal, filterType, comparator } = filters[dataField];
if (filterType === 'TEXT') {
if (comparator === Comparator.LIKE) {
valid = row[dataField].toString().indexOf(filterVal) > -1;
} else {
valid = row[dataField] === filterVal;
}
}
if (!valid) break;
}
return valid;
});
this.setState(() => ({
page,
data: result.slice(currentIndex, currentIndex + sizePerPage),
totalSize: result.length,
sizePerPage
}));
}, 2000);
}
render() {
const { data, sizePerPage, page } = this.state;
return (
<RemoteAll
data={ data }
page={ page }
sizePerPage={ sizePerPage }
totalSize={ this.state.totalSize }
onTableChange={ this.handleTableChange }
/>
);
}
}
`;
const RemoteAll = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<h3>When <code>remote.pagination</code> is enabled, the filtering,
sorting and searching will also change to remote mode automatically</h3>
<BootstrapTable
remote={ { pagination: true } }
keyField="id"
data={ data }
columns={ columns }
filter={ filterFactory() }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
RemoteAll.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),
totalSize: products.length,
sizePerPage: 10
};
this.handleTableChange = this.handleTableChange.bind(this);
}
handleTableChange = (type, { page, sizePerPage, filters }) => {
const currentIndex = (page - 1) * sizePerPage;
setTimeout(() => {
const result = products.filter((row) => {
let valid = true;
for (const dataField in filters) {
const { filterVal, filterType, comparator } = filters[dataField];
if (filterType === 'TEXT') {
if (comparator === Comparator.LIKE) {
valid = row[dataField].toString().indexOf(filterVal) > -1;
} else {
valid = row[dataField] === filterVal;
}
}
if (!valid) break;
}
return valid;
});
this.setState(() => ({
page,
data: result.slice(currentIndex, currentIndex + sizePerPage),
totalSize: result.length,
sizePerPage
}));
}, 2000);
}
render() {
const { data, sizePerPage, page } = this.state;
return (
<RemoteAll
data={ data }
page={ page }
sizePerPage={ sizePerPage }
totalSize={ this.state.totalSize }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View File

@@ -0,0 +1,168 @@
import React from 'react';
import PropTypes from 'prop-types';
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 cellEditFactory from 'react-bootstrap-table2-editor';
// ...
const RemoteCellEdit = (props) => {
const cellEdit = {
mode: 'click',
errorMessage: props.errorMessage
};
return (
<div>
<BootstrapTable
remote={ { cellEdit: true } }
keyField="id"
data={ props.data }
columns={ columns }
cellEdit={ cellEditFactory(cellEdit) }
onTableChange={ props.onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
};
RemoteCellEdit.propTypes = {
data: PropTypes.array.isRequired,
onTableChange: PropTypes.func.isRequired,
errorMessage: PropTypes.string.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
data: products,
errorMessage: null
};
}
handleTableChange = (type, { data, cellEdit: { rowId, dataField, newValue } }) => {
setTimeout(() => {
if (newValue === 'test' && dataField === 'name') {
this.setState(() => ({
data,
errorMessage: 'Oops, product name shouldn't be "test"'
}));
} else {
const result = data.map((row) => {
if (row.id === rowId) {
const newRow = { ...row };
newRow[dataField] = newValue;
return newRow;
}
return row;
});
this.setState(() => ({
data: result,
errorMessage: null
}));
}
}, 2000);
}
render() {
return (
<RemoteCellEdit
data={ this.state.data }
errorMessage={ this.state.errorMessage }
onTableChange={ this.handleTableChange }
/>
);
}
}
`;
const RemoteCellEdit = (props) => {
const cellEdit = {
mode: 'click',
errorMessage: props.errorMessage
};
return (
<div>
<BootstrapTable
remote={ { cellEdit: true } }
keyField="id"
data={ props.data }
columns={ columns }
cellEdit={ cellEditFactory(cellEdit) }
onTableChange={ props.onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
};
RemoteCellEdit.propTypes = {
data: PropTypes.array.isRequired,
onTableChange: PropTypes.func.isRequired,
errorMessage: PropTypes.string.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
data: products,
errorMessage: null
};
}
handleTableChange = (type, { data, cellEdit: { rowId, dataField, newValue } }) => {
setTimeout(() => {
if (newValue === 'test' && dataField === 'name') {
this.setState(() => ({
data,
errorMessage: 'Oops, product name shouldn\'t be "test"'
}));
} else {
const result = data.map((row) => {
if (row.id === rowId) {
const newRow = { ...row };
newRow[dataField] = newValue;
return newRow;
}
return row;
});
this.setState(() => ({
data: result,
errorMessage: null
}));
}
}, 2000);
}
render() {
return (
<RemoteCellEdit
data={ this.state.data }
errorMessage={ this.state.errorMessage }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View File

@@ -0,0 +1,105 @@
/* eslint guard-for-in: 0 */
/* eslint no-restricted-syntax: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter, Comparator } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(17);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}];
const sourceCode = `\
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()
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
`;
const RemoteFilter = props => (
<div>
<BootstrapTable
remote={ { filter: true } }
keyField="id"
data={ props.data }
columns={ columns }
filter={ filterFactory() }
onTableChange={ props.onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
RemoteFilter.propTypes = {
data: PropTypes.array.isRequired,
onTableChange: PropTypes.func.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
data: products
};
}
handleTableChange = (type, { filters }) => {
setTimeout(() => {
const result = products.filter((row) => {
let valid = true;
for (const dataField in filters) {
const { filterVal, filterType, comparator } = filters[dataField];
if (filterType === 'TEXT') {
if (comparator === Comparator.LIKE) {
valid = row[dataField].toString().indexOf(filterVal) > -1;
} else {
valid = row[dataField] === filterVal;
}
}
if (!valid) break;
}
return valid;
});
this.setState(() => ({
data: result
}));
}, 2000);
}
render() {
return (
<RemoteFilter
data={ this.state.data }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View File

@@ -0,0 +1,133 @@
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import PropTypes from 'prop-types';
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 RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => (
<div>
<BootstrapTable
remote
keyField="id"
data={ data }
columns={ columns }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1,
data: products.slice(0, 10),
sizePerPage: 10
};
}
handleTableChange = ({ 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>
<BootstrapTable
remote
keyField="id"
data={ data }
columns={ columns }
pagination={ paginationFactory({ page, sizePerPage, totalSize }) }
onTableChange={ onTableChange }
/>
<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,106 @@
/* eslint no-restricted-syntax: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(5);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
sort: true
}, {
dataField: 'price',
text: 'Product Price',
sort: true
}];
const sourceCode = `\
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()
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
`;
const RemoteSort = props => (
<div>
<BootstrapTable
remote={ { sort: true } }
keyField="id"
data={ props.data }
columns={ columns }
onTableChange={ props.onTableChange }
/>
<Code>{ sourceCode }</Code>
</div>
);
RemoteSort.propTypes = {
data: PropTypes.array.isRequired,
onTableChange: PropTypes.func.isRequired
};
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
data: products
};
}
handleTableChange = (type, { sortField, sortOrder, data }) => {
setTimeout(() => {
let result;
if (sortOrder === 'asc') {
result = data.sort((a, b) => {
if (a[sortField] > b[sortField]) {
return 1;
} else if (b[sortField] > a[sortField]) {
return -1;
}
return 0;
});
} else {
result = data.sort((a, b) => {
if (a[sortField] > b[sortField]) {
return -1;
} else if (b[sortField] > a[sortField]) {
return 1;
}
return 0;
});
}
this.setState(() => ({
data: result
}));
}, 2000);
}
render() {
return (
<RemoteSort
data={ this.state.data }
onTableChange={ this.handleTableChange }
/>
);
}
}
export default Container;

View File

@@ -0,0 +1,65 @@
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,
clickToEdit: true
};
const cellEdit = {
mode: 'click'
};
const sourceCode = `\
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 // Click to edit cell also
};
const cellEdit = {
mode: 'click'
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } cellEdit={ cellEdit } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,55 @@
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
};
const sourceCode = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,59 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
hideSelectColumn: true,
bgColor: '#00BFFF'
};
const sourceCode = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
hideSelectColumn: true,
bgColor: '#00BFFF'
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -17,8 +17,9 @@ const columns = [{
text: 'Product Price'
}];
const selectRowProp = {
mode: 'checkbox'
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
const sourceCode = `\
@@ -33,21 +34,22 @@ const columns = [{
text: 'Product Price'
}];
const selectRowProp = {
mode: 'checkbox'
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
<BootstrapTableful
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRowProp }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } selectRow={ selectRowProp } />
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,57 @@
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,
nonSelectable: [0, 2, 4]
};
const sourceCode = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
nonSelectable: [0, 2, 4]
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,92 @@
/* 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'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow1 = {
mode: 'checkbox',
clickToSelect: true,
bgColor: '#00BFFF'
};
const selectRow2 = {
mode: 'checkbox',
clickToSelect: true,
bgColor: (row, rowIndex) => (rowIndex > 1 ? '#00BFFF' : '#00FFFF')
};
const sourceCode1 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
bgColor: '#00BFFF'
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
const sourceCode2 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
bgColor: (row, rowIndex) => (rowIndex > 1 ? '#00BFFF' : '#00FFFF')
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow2 } />
<Code>{ sourceCode2 }</Code>
</div>
);

View File

@@ -0,0 +1,94 @@
/* 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'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow1 = {
mode: 'checkbox',
clickToSelect: true,
classes: 'selection-row'
};
const selectRow2 = {
mode: 'checkbox',
clickToSelect: true,
classes: (row, rowIndex) =>
(rowIndex > 1 ? 'row-index-bigger-than-2101' : 'row-index-small-than-2101')
};
const sourceCode1 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
classes: 'selection-row'
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
const sourceCode2 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
classes: (row, rowIndex) =>
(rowIndex > 1 ? 'row-index-bigger-than-2101' : 'row-index-small-than-2101')
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow2 } />
<Code>{ sourceCode2 }</Code>
</div>
);

View File

@@ -0,0 +1,66 @@
/* 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 selectRow = {
mode: 'checkbox',
clickToSelect: true,
onSelect: (row, isSelect, rowIndex) => {
console.log(row.id);
console.log(isSelect);
console.log(rowIndex);
},
onSelectAll: (isSelect, rows) => {
console.log(isSelect);
console.log(rows);
}
};
const sourceCode = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,98 @@
/* 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'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow1 = {
mode: 'checkbox',
clickToSelect: true,
style: { backgroundColor: '#c8e6c9' }
};
const selectRow2 = {
mode: 'checkbox',
clickToSelect: true,
style: (row, rowIndex) => {
const backgroundColor = rowIndex > 1 ? '#00BFFF' : '#00FFFF';
return { backgroundColor };
}
};
const sourceCode1 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
style: { backgroundColor: '#c8e6c9' }
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
const sourceCode2 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
style: (row, rowIndex) => {
const backgroundColor = rowIndex > 1 ? '#00BFFF' : '#00FFFF';
return { backgroundColor };
}
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow2 } />
<Code>{ sourceCode2 }</Code>
</div>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -17,8 +17,9 @@ const columns = [{
text: 'Product Price'
}];
const selectRowProp = {
mode: 'radio'
const selectRow = {
mode: 'radio',
clickToSelect: true
};
const sourceCode = `\
@@ -33,21 +34,22 @@ const columns = [{
text: 'Product Price'
}];
const selectRowProp = {
mode: 'radio'
const selectRow = {
mode: 'radio',
clickToSelect: true
};
<BootstrapTableful
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRowProp }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } selectRow={ selectRowProp } />
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,81 @@
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 rowClasses1 = 'custom-row-class';
const sourceCode1 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowClasses = 'custom-row-class';
<BootstrapTable keyField='id' data={ products } columns={ columns } rowClasses={ rowClasses } />
`;
const rowClasses2 = (row, rowIndex) => {
let classes = null;
if (rowIndex > 2) {
classes = 'index-bigger-than-two';
}
return classes;
};
const sourceCode2 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowClasses = (row, rowIndex) => {
let classes = null;
if (rowIndex > 2) {
classes = 'index-bigger-than-two';
}
return classes;
};
<BootstrapTable keyField='id' data={ products } columns={ columns } rowClasses={ rowClasses } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } rowClasses={ rowClasses1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } rowClasses={ rowClasses2 } />
<Code>{ sourceCode2 }</Code>
</div>
);

View File

@@ -0,0 +1,54 @@
/* 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) => {
console.log('click on row');
}
};
const sourceCode = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowEvents = {
onClick: (e) => {
console.log('click on row');
}
};
<BootstrapTable keyField='id' data={ products } columns={ columns } rowStyle={ rowStyle } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } rowEvents={ rowEvents } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,93 @@
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 rowStyle1 = { backgroundColor: '#c8e6c9' };
const sourceCode1 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowStyle = { backgroundColor: '#c8e6c9' };
<BootstrapTable keyField='id' data={ products } columns={ columns } rowStyle={ rowStyle } />
`;
const rowStyle2 = (row, rowIndex) => {
const style = {};
if (row.id > 3) {
style.backgroundColor = '#c8e6c9';
} else {
style.backgroundColor = '#00BFFF';
}
if (rowIndex > 2) {
style.fontWeight = 'bold';
style.color = 'white';
}
return style;
};
const sourceCode2 = `\
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowStyle2 = (row, rowIndex) => {
const style = {};
if (row.id > 3) {
style.backgroundColor = '#c8e6c9';
} else {
style.backgroundColor = '#00BFFF';
}
if (rowIndex > 2) {
style.fontWeight = 'bold';
style.color = 'white';
}
return style;
};
<BootstrapTable keyField='id' data={ products } columns={ columns } rowStyle={ rowStyle2 } />
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } rowStyle={ rowStyle1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } rowStyle={ rowStyle2 } />
<Code>{ sourceCode2 }</Code>
</div>
);

View File

@@ -2,7 +2,7 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -49,12 +49,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,69 @@
/* eslint react/prefer-stateless-function: 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
}, {
dataField: 'price',
text: 'Product Price',
sort: true
}];
const defaultSorted = [{
dataField: 'name',
order: 'desc'
}];
const sourceCode = `\
const columns = [{
dataField: 'id',
text: 'Product ID',
sort: true
}, {
dataField: 'name',
text: 'Product Name',
sort: true
}, {
dataField: 'price',
text: 'Product Price',
sort: true
}];
const defaultSorted = [{
dataField: 'name',
order: 'desc'
}];
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
defaultSorted={ defaultSorted }
/>
`;
class DefaultSortTable extends React.PureComponent {
render() {
return (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } defaultSorted={ defaultSorted } />
<Code>{ sourceCode }</Code>
</div>
);
}
}
export default DefaultSortTable;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { BootstrapTableful } from 'react-bootstrap-table2';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
@@ -33,12 +33,12 @@ const columns = [{
text: 'Product Price'
}];
<BootstrapTableful keyField='id' data={ products } columns={ columns } />
<BootstrapTable keyField='id' data={ products } columns={ columns } />
`;
export default () => (
<div>
<BootstrapTableful keyField="id" data={ products } columns={ columns } />
<BootstrapTable keyField="id" data={ products } columns={ columns } />
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -0,0 +1,61 @@
/* eslint
no-unused-vars: 0
arrow-body-style: 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 headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => (
sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc'
);
const columns = [{
dataField: 'id',
text: 'Product ID',
sort: true,
headerSortingClasses
}, {
dataField: 'name',
text: 'Product Name',
sort: true,
headerSortingClasses
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => (
sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc'
);
const columns = [{
dataField: 'id',
text: 'Product ID',
sort: true,
headerSortingClasses
}, {
dataField: 'name',
text: 'Product Name',
sort: true,
headerSortingClasses
}, {
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

@@ -0,0 +1,54 @@
/* 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 headerSortingStyle = { backgroundColor: '#c8e6c9' };
const columns = [{
dataField: 'id',
text: 'Product ID',
sort: true,
headerSortingStyle
}, {
dataField: 'name',
text: 'Product Name',
sort: true,
headerSortingStyle
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
const headerSortingStyle = { backgroundColor: '#c8e6c9' };
const columns = [{
dataField: 'id',
text: 'Product ID',
sort: true,
headerSortingStyle
}, {
dataField: 'name',
text: 'Product Name',
sort: true,
headerSortingStyle
}, {
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

@@ -24,13 +24,13 @@ export default class Welcome extends React.Component {
<h1 className="welcome-title">react-bootstrap-table2</h1>
<span
className="welcome-sub-title"
ref={(el) => { this.el = el; }}
ref={ (el) => { this.el = el; } }
/>
</div>
<a href="https://github.com/react-bootstrap-table/react-bootstrap-table2" 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: '#009688', 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="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" />
</svg>
</a>

View File

@@ -1,12 +1,14 @@
{
"name": "react-bootstrap-table2-example",
"version": "0.0.1",
"version": "0.0.3",
"description": "",
"main": "index.js",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
"gh-pages:clean": "rimraf ./storybook-static",
"gh-pages:build": "build-storybook"
},
"author": "",
"license": "ISC",
@@ -16,11 +18,15 @@
"react-dom": "^15.0.0"
},
"dependencies": {
"bootstrap": "^3.3.7",
"react-bootstrap-table2": "0.0.1"
"bootstrap": "^3.3.7"
},
"devDependencies": {
"@storybook/addon-console": "^1.0.0",
"@storybook/react": "^3.2.8",
"babel-preset-env": "^1.6.1",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0",
"typed.js": "^2.0.5"
}
}

View File

@@ -1,18 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>react-bootstrap-table demo</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.js"></script>
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script src="https://use.fontawesome.com/f52b8fd2c4.js"></script> -->
</head>
<body>
<div id="example"></div>
</body>
</html>

View File

@@ -1,66 +0,0 @@
import React from 'react';
import ReactDom from 'react-dom';
import { BootstrapTableful } from 'react-bootstrap-table2';
const products = [];
function addProducts(quantity) {
const startId = products.length;
for (let i = 0; i < quantity; i += 1) {
const id = startId + i;
products.push({
id,
name: `Item name ${id}`,
price: 2100 + i,
nest: {
address: 'Address 1',
postcal: '0922-1234'
}
});
}
}
addProducts(5);
const columns = [{
dataField: 'id',
text: 'Product ID',
style: {
backgroundColor: 'red'
},
headerTitle: (column, colIndex) => {
console.log(column);
console.log(colIndex);
return 'yes~~~ oh';
},
classes: 'my-xxx'
}, {
dataField: 'name',
text: 'Product Name',
headerTitle: true,
formatter: (cell, row) =>
(<h3>{ cell }::: ${ row.price }</h3>)
}, {
dataField: 'price',
text: 'Product Price',
style: (cell, row, colIndex) => {
console.log(cell);
console.log(row);
console.log(colIndex);
return {
backgroundColor: 'blue'
};
}
}, {
dataField: 'nest.address',
text: 'Address'
}, {
dataField: 'nest.postcal',
text: 'Postal'
}];
ReactDom.render(
<BootstrapTableful keyField="id" data={ products } columns={ columns } />,
document.getElementById('example'));

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