mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 13:40:07 +00:00
Compare commits
48 Commits
react-boot
...
feat/dnd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d2a6a1b23 | ||
|
|
bb752fcec8 | ||
|
|
5a6b7e122d | ||
|
|
a7ae524c49 | ||
|
|
a23599f52f | ||
|
|
c50853b16d | ||
|
|
3f74542c98 | ||
|
|
47aa41b8fa | ||
|
|
67ed2e6c80 | ||
|
|
794a97956d | ||
|
|
78ca01bb1a | ||
|
|
b79dbc80f6 | ||
|
|
3f21a67620 | ||
|
|
9e3ae385ce | ||
|
|
c6ea19fe8a | ||
|
|
a5b42dca92 | ||
|
|
28f3c33db3 | ||
|
|
2530a70c00 | ||
|
|
569dd61463 | ||
|
|
68264b45ce | ||
|
|
e251068657 | ||
|
|
e4fbb284b4 | ||
|
|
a6afc9d9a8 | ||
|
|
a0ba41c103 | ||
|
|
4a16cb314d | ||
|
|
98a04a5710 | ||
|
|
c22a2a1d71 | ||
|
|
9bc25c9d3e | ||
|
|
4554db02d2 | ||
|
|
b7fac973d2 | ||
|
|
6925358631 | ||
|
|
27c3cdab29 | ||
|
|
bc0c048735 | ||
|
|
a4c1090a0f | ||
|
|
5fac4540a1 | ||
|
|
f7a06401ae | ||
|
|
858ad9543b | ||
|
|
abf618ce6d | ||
|
|
ea6cb78302 | ||
|
|
bacbfdbbf0 | ||
|
|
465212ff35 | ||
|
|
2a58f99a97 | ||
|
|
7bda61f5be | ||
|
|
7220b2d073 | ||
|
|
f7a1c91904 | ||
|
|
ea827bfeb5 | ||
|
|
f1f4bd784d | ||
|
|
569c22ba49 |
41
README.md
41
README.md
@@ -1,43 +1,56 @@
|
|||||||
# react-bootstrap-table2
|
# react-bootstrap-table2
|
||||||
|
|
||||||
[](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2)
|
[](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2)
|
||||||
Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
|
Rebuilt of [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
|
||||||
|
|
||||||
> `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to some guys already used it
|
> Note that `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to the name being already taken.
|
||||||
|
|
||||||
`react-bootstrap-table2` separate some functionalities from core modules to other modules like following:
|
`react-bootstrap-table2` separates some functionalities from its core modules to other modules as listed in the following:
|
||||||
|
|
||||||
* [`react-bootstrap-table-next`](https://www.npmjs.com/package/react-bootstrap-table-next)
|
- [`react-bootstrap-table-next`](https://www.npmjs.com/package/react-bootstrap-table-next)
|
||||||
* [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter)
|
- [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter)
|
||||||
* [`react-bootstrap-table2-editor`](https://www.npmjs.com/package/react-bootstrap-table2-editor)
|
- [`react-bootstrap-table2-editor`](https://www.npmjs.com/package/react-bootstrap-table2-editor)
|
||||||
* [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator)
|
- [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator)
|
||||||
* [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay)
|
- [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay)
|
||||||
* [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit)
|
- [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit)
|
||||||
|
|
||||||
This can help your application with less bundled size and also help us have clean design to avoid handling to much logic in kernel module(SRP).
|
Not only does this reduce the bundle size of your apps but also helps us have a cleaner design to avoid handling too much logic in the kernel module(SRP).
|
||||||
|
|
||||||
## Migration
|
## Migration
|
||||||
If you are the user from legacy [`react-bootstrap-table`](https://github.com/AllenFang/react-bootstrap-table/), please have a look on [this](./docs/migration.md).
|
|
||||||
|
If you are coming from the legacy [`react-bootstrap-table`](https://github.com/AllenFang/react-bootstrap-table/), please check out the [migration guide](./docs/migration.md).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html).
|
See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html).
|
||||||
|
|
||||||
## Online Demo
|
## Online Demo
|
||||||
|
|
||||||
See `react-bootstrap-table2` [storybook](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html).
|
See `react-bootstrap-table2` [storybook](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html).
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
See [release plans](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/release-plan.html).
|
See [release plans](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/release-plan.html).
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
Please check [development guide](./docs/development.md).
|
|
||||||
|
|
||||||
## How should I run storybook example in my local?
|
Please check the [development guide](./docs/development.md).
|
||||||
|
|
||||||
|
## Running storybook example on your local machine
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
# Clone the repo
|
||||||
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
||||||
|
|
||||||
|
# change dir to the cloned repo
|
||||||
$ cd react-bootstrap-table2
|
$ cd react-bootstrap-table2
|
||||||
|
|
||||||
|
# Install all dependencies with yarn
|
||||||
$ yarn install
|
$ yarn install
|
||||||
|
|
||||||
|
# Start the stroybook server, then go to localhost:6006
|
||||||
$ yarn storybook
|
$ yarn storybook
|
||||||
$ Go to localhost:6006
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Storybook examples: [`packages/react-bootstrap-table2-example/examples`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/master/packages/react-bootstrap-table2-example/examples)**
|
**Storybook examples: [`packages/react-bootstrap-table2-example/examples`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/master/packages/react-bootstrap-table2-example/examples)**
|
||||||
|
|||||||
@@ -62,6 +62,24 @@ const cellEdit = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to perform a async `beforeSaveCell`, you can do it like that:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const cellEdit: {
|
||||||
|
// omit...
|
||||||
|
beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Do you want to accep this change?')) {
|
||||||
|
done(); // contine to save the changes
|
||||||
|
} else {
|
||||||
|
done(false); // reject the changes
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='afterSaveCell'>cellEdit.afterSaveCell - [Function]</a>
|
### <a name='afterSaveCell'>cellEdit.afterSaveCell - [Function]</a>
|
||||||
This callback function will be called after updating cell.
|
This callback function will be called after updating cell.
|
||||||
|
|
||||||
|
|||||||
@@ -379,17 +379,27 @@ A new `String` will be the result of element headerAlign.
|
|||||||
|
|
||||||
|
|
||||||
## <a name='events'>column.events - [Object]</a>
|
## <a name='events'>column.events - [Object]</a>
|
||||||
You can assign any [HTML Event](https://www.w3schools.com/tags/ref_eventattributes.asp) on table column via event property:
|
You can assign any [HTML Event](https://www.w3schools.com/tags/ref_eventattributes.asp) on table column via `events` property.
|
||||||
|
|
||||||
|
`react-bootstrap-table2` currently only support following events which will receive some specific information:
|
||||||
|
|
||||||
|
* onClick
|
||||||
|
* onDoubleClick
|
||||||
|
* onMouseEnter
|
||||||
|
* onMouseLeave
|
||||||
|
* onContextMenu
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
// omit...
|
// omit...
|
||||||
events: {
|
events: {
|
||||||
onClick: e => { ... }
|
onClick: (e, column, columnIndex, row, rowIndex) => { ... },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the events is not listed above, the callback function will only pass the `event` object.
|
||||||
|
|
||||||
## <a name='headerEvents'>column.headerEvents - [Object]</a>
|
## <a name='headerEvents'>column.headerEvents - [Object]</a>
|
||||||
`headerEvents` same as [`column.events`](#events) but this is for header column.
|
`headerEvents` same as [`column.events`](#events) but this is for header column.
|
||||||
|
|
||||||
@@ -543,6 +553,28 @@ The return value can be a bool or an object. If your validation is pass, return
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to perform a asycn validation, you can do it like this:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// omit...
|
||||||
|
validator: (newValue, row, column, done) => {
|
||||||
|
settimeout(() => {
|
||||||
|
// async validation ok
|
||||||
|
return done();
|
||||||
|
|
||||||
|
// async validation not ok
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'SOME_REASON_HERE'
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 2000);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## <a name='editCellStyle'>column.editCellStyle - [Object | Function]</a>
|
## <a name='editCellStyle'>column.editCellStyle - [Object | Function]</a>
|
||||||
You can use `column.editCellStyle` to custom the style of `<td>` when cell editing. It like most of customizable functionality, it also accept a callback function with following params:
|
You can use `column.editCellStyle` to custom the style of `<td>` when cell editing. It like most of customizable functionality, it also accept a callback function with following params:
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
### Setup
|
### Setup
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
$ git clone https://github.com/react-bootstrap-table/react-bootstrap-table2.git
|
||||||
$ cd react-bootstrap-table
|
$ cd react-bootstrap-table2
|
||||||
$ npm install
|
$ npm install
|
||||||
$ lerna bootstrap # ./node_modules/.bin/lerna bootstrap
|
$ lerna bootstrap # ./node_modules/.bin/lerna bootstrap
|
||||||
```
|
```
|
||||||
@@ -25,4 +25,4 @@ $ npm run storybook
|
|||||||
$ npm test
|
$ npm test
|
||||||
$ npm run test:watch # for watch mode
|
$ npm run test:watch # for watch mode
|
||||||
$ npm run test:coverage # generate coverage report
|
$ npm run test:coverage # generate coverage report
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -211,18 +211,44 @@ const selectRow = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> If you want to reject current select action, just return `false`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
onSelect: (row, isSelect, rowIndex, e) => {
|
||||||
|
if (SOME_CONDITION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='onSelectAll'>selectRow.onSelectAll - [Function]</a>
|
### <a name='onSelectAll'>selectRow.onSelectAll - [Function]</a>
|
||||||
This callback function will be called when select/unselect all and it only work when you configure [`selectRow.mode`](#mode) as `checkbox`.
|
This callback function will be called when select/unselect all and it only work when you configure [`selectRow.mode`](#mode) as `checkbox`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const selectRow = {
|
const selectRow = {
|
||||||
mode: 'checkbox',
|
mode: 'checkbox',
|
||||||
onSelectAll: (isSelect, results, e) => {
|
onSelectAll: (isSelect, rows, e) => {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> If you want to control the final selection result, just return a row key array:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
onSelectAll: (isSelect, rows, e) => {
|
||||||
|
if (isSelect && SOME_CONDITION) {
|
||||||
|
return [1, 3, 4]; // finally, key 1, 3, 4 will being selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### <a name='hideSelectColumn'>selectRow.hideSelectColumn - [Bool]</a>
|
### <a name='hideSelectColumn'>selectRow.hideSelectColumn - [Bool]</a>
|
||||||
Default is `false`, if you don't want to have a selection column, give this prop as `true`
|
Default is `false`, if you don't want to have a selection column, give this prop as `true`
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-editor",
|
"name": "react-bootstrap-table2-editor",
|
||||||
"version": "1.2.0",
|
"version": "1.2.2",
|
||||||
"description": "it's the editor addon for react-bootstrap-table2",
|
"description": "it's the editor addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export default (
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.doUpdate = this.doUpdate.bind(this);
|
||||||
this.startEditing = this.startEditing.bind(this);
|
this.startEditing = this.startEditing.bind(this);
|
||||||
this.escapeEditing = this.escapeEditing.bind(this);
|
this.escapeEditing = this.escapeEditing.bind(this);
|
||||||
this.completeEditing = this.completeEditing.bind(this);
|
this.completeEditing = this.completeEditing.bind(this);
|
||||||
@@ -55,11 +56,36 @@ export default (
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleCellUpdate(row, column, newValue) {
|
handleCellUpdate(row, column, newValue) {
|
||||||
const { keyField, cellEdit, data } = this.props;
|
const { cellEdit } = this.props;
|
||||||
const { beforeSaveCell, afterSaveCell } = cellEdit.options;
|
const { beforeSaveCell } = cellEdit.options;
|
||||||
const oldValue = _.get(row, column.dataField);
|
const oldValue = _.get(row, column.dataField);
|
||||||
|
const beforeSaveCellDone = (result = true) => {
|
||||||
|
if (result) {
|
||||||
|
this.doUpdate(row, column, newValue);
|
||||||
|
} else {
|
||||||
|
this.escapeEditing();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_.isFunction(beforeSaveCell)) {
|
||||||
|
const result = beforeSaveCell(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
beforeSaveCellDone
|
||||||
|
);
|
||||||
|
if (_.isObject(result) && result.async) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.doUpdate(row, column, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
doUpdate(row, column, newValue) {
|
||||||
|
const { keyField, cellEdit, data } = this.props;
|
||||||
|
const { afterSaveCell } = cellEdit.options;
|
||||||
const rowId = _.get(row, keyField);
|
const rowId = _.get(row, keyField);
|
||||||
if (_.isFunction(beforeSaveCell)) beforeSaveCell(oldValue, newValue, row, column);
|
const oldValue = _.get(row, column.dataField);
|
||||||
if (isRemoteCellEdit()) {
|
if (isRemoteCellEdit()) {
|
||||||
handleCellChange(rowId, column.dataField, newValue);
|
handleCellChange(rowId, column.dataField, newValue);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ export default (_, onStartEdit) =>
|
|||||||
this.handleClick = this.handleClick.bind(this);
|
this.handleClick = this.handleClick.bind(this);
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
this.beforeComplete = this.beforeComplete.bind(this);
|
this.beforeComplete = this.beforeComplete.bind(this);
|
||||||
|
this.asyncbeforeCompete = this.asyncbeforeCompete.bind(this);
|
||||||
|
this.displayErrorMessage = this.displayErrorMessage.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
invalidMessage: null
|
invalidMessage: null
|
||||||
};
|
};
|
||||||
@@ -79,16 +81,41 @@ export default (_, onStartEdit) =>
|
|||||||
}, timeToCloseMessage);
|
}, timeToCloseMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
displayErrorMessage(message) {
|
||||||
|
this.setState(() => ({
|
||||||
|
invalidMessage: message
|
||||||
|
}));
|
||||||
|
this.createTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncbeforeCompete(newValue) {
|
||||||
|
return (result = { valid: true }) => {
|
||||||
|
const { valid, message } = result;
|
||||||
|
const { onUpdate, row, column } = this.props;
|
||||||
|
if (!valid) {
|
||||||
|
this.displayErrorMessage(message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onUpdate(row, column, newValue);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
beforeComplete(newValue) {
|
beforeComplete(newValue) {
|
||||||
const { onUpdate, row, column } = this.props;
|
const { onUpdate, row, column } = this.props;
|
||||||
if (_.isFunction(column.validator)) {
|
if (_.isFunction(column.validator)) {
|
||||||
const validateForm = column.validator(newValue, row, column);
|
const validateForm = column.validator(
|
||||||
if (_.isObject(validateForm) && !validateForm.valid) {
|
newValue,
|
||||||
this.setState(() => ({
|
row,
|
||||||
invalidMessage: validateForm.message
|
column,
|
||||||
}));
|
this.asyncbeforeCompete(newValue)
|
||||||
this.createTimer();
|
);
|
||||||
return;
|
if (_.isObject(validateForm)) {
|
||||||
|
if (validateForm.async) {
|
||||||
|
return;
|
||||||
|
} else if (!validateForm.valid) {
|
||||||
|
this.displayErrorMessage(validateForm.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onUpdate(row, column, newValue);
|
onUpdate(row, column, newValue);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
const EditorIndicator = ({ invalidMessage }) =>
|
const EditorIndicator = ({ invalidMessage }) =>
|
||||||
(
|
(
|
||||||
<div className="alert alert-danger fade in">
|
<div className="alert alert-danger in" role="alert">
|
||||||
<strong>{ invalidMessage }</strong>
|
<strong>{ invalidMessage }</strong>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -235,7 +235,8 @@ describe('CellEditContext', () => {
|
|||||||
|
|
||||||
it('should call cellEdit.beforeSaveCell correctly', () => {
|
it('should call cellEdit.beforeSaveCell correctly', () => {
|
||||||
expect(beforeSaveCell).toHaveBeenCalledTimes(1);
|
expect(beforeSaveCell).toHaveBeenCalledTimes(1);
|
||||||
expect(beforeSaveCell).toHaveBeenCalledWith(oldValue, newValue, row, column);
|
expect(beforeSaveCell)
|
||||||
|
.toHaveBeenCalledWith(oldValue, newValue, row, column, expect.anything());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
86
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-hooks-table.js
vendored
Normal file
86
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-hooks-table.js
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
/* eslint no-console: 0 */
|
||||||
|
/* eslint no-alert: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
function beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Do you want to accep this change?')) {
|
||||||
|
done(true);
|
||||||
|
} else {
|
||||||
|
done(false);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
beforeSaveCell
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
function beforeSaveCell(oldValue, newValue, row, column, done) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (confirm('Do you want to accep this change?')) {
|
||||||
|
done(true);
|
||||||
|
} else {
|
||||||
|
done(false);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h2>You will get a confirm prompt when you try to save a cell</h2>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
beforeSaveCell
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
101
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-validator-table.js
vendored
Normal file
101
packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-async-validator-table.js
vendored
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
validator: (newValue, row, column, done) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (isNaN(newValue)) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should be numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (newValue < 2000) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should bigger than 2000'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done();
|
||||||
|
}, 2000);
|
||||||
|
return {
|
||||||
|
async: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price',
|
||||||
|
validator: (newValue, row, column, done) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (isNaN(newValue)) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should be numeric'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (newValue < 2000) {
|
||||||
|
return done({
|
||||||
|
valid: false,
|
||||||
|
message: 'Price should bigger than 2000'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return done();
|
||||||
|
}, 2000);
|
||||||
|
return {
|
||||||
|
async: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
blurToSave: true
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3>Product Price should bigger than $2000</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
cellEdit={ cellEditFactory({
|
||||||
|
mode: 'click',
|
||||||
|
blurToSave: true
|
||||||
|
}) }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -103,7 +103,7 @@ const columns = [{
|
|||||||
}, {
|
}, {
|
||||||
dataField: 'quality',
|
dataField: 'quality',
|
||||||
text: 'Product Quality',
|
text: 'Product Quality',
|
||||||
editorRenderer: (editorProps, value, row, rowIndex, columnIndex) => (
|
editorRenderer: (editorProps, value, row, column, rowIndex, columnIndex) => (
|
||||||
<QualityRanger { ...editorProps } value={ value } />
|
<QualityRanger { ...editorProps } value={ value } />
|
||||||
)
|
)
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/* eslint max-len: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsQualityGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsQualityGenerator(6);
|
||||||
|
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: 0, label: 'good' },
|
||||||
|
{ value: 1, label: 'Bad' },
|
||||||
|
{ value: 2, label: 'unknown' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
|
||||||
|
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: 0, label: 'good' },
|
||||||
|
{ value: 1, label: 'Bad' },
|
||||||
|
{ value: 2, label: 'unknown' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<h3><code>selectFilter.options</code> accept an Array and we keep that order when rendering the options</h3>
|
||||||
|
<BootstrapTable
|
||||||
|
keyField="id"
|
||||||
|
data={ products }
|
||||||
|
columns={ columns }
|
||||||
|
filter={ filterFactory() }
|
||||||
|
/>
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/* eslint no-unused-vars: 0 */
|
/* eslint no-unused-vars: 0 */
|
||||||
/* eslint no-alert: 0 */
|
/* eslint no-alert: 0 */
|
||||||
|
/* eslint no-console: 0 */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
@@ -12,7 +13,22 @@ const columns = [{
|
|||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
text: 'Product ID',
|
text: 'Product ID',
|
||||||
events: {
|
events: {
|
||||||
onClick: () => alert('Click on Product ID field')
|
onClick: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
alert('Click on Product ID field');
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
console.log('onMouseEnter on Product ID field');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
dataField: 'name',
|
dataField: 'name',
|
||||||
@@ -29,7 +45,22 @@ const columns = [{
|
|||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
text: 'Product ID',
|
text: 'Product ID',
|
||||||
events: {
|
events: {
|
||||||
onClick: () => alert('Click on Product ID field')
|
onClick: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
alert('Click on Product ID field');
|
||||||
|
},
|
||||||
|
onMouseEnter: (e, column, columnIndex, row, rowIndex) => {
|
||||||
|
console.log(e);
|
||||||
|
console.log(column);
|
||||||
|
console.log(columnIndex);
|
||||||
|
console.log(row);
|
||||||
|
console.log(rowIndex);
|
||||||
|
console.log('onMouseEnter on Product ID field');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
dataField: 'name',
|
dataField: 'name',
|
||||||
@@ -44,7 +75,7 @@ const columns = [{
|
|||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<h3>Try to Click on Product ID columns</h3>
|
<h3>Try to Click or Mouse over on Product ID columns</h3>
|
||||||
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||||
<Code>{ sourceCode }</Code>
|
<Code>{ sourceCode }</Code>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React from 'react';
|
|||||||
|
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
import Code from 'components/common/code-block';
|
import Code from 'components/common/code-block';
|
||||||
import { productsGenerator } from 'utils/common';
|
import { productsGenerator, withOnSale } from 'utils/common';
|
||||||
|
|
||||||
const products = productsGenerator();
|
const products = withOnSale(productsGenerator());
|
||||||
|
|
||||||
function priceFormatter(cell, row) {
|
function priceFormatter(cell, row) {
|
||||||
if (row.onSale) {
|
if (row.onSale) {
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ const expandRow = {
|
|||||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
showExpandColumn: true
|
showExpandColumn: true,
|
||||||
|
expandByColumnOnly: true
|
||||||
};
|
};
|
||||||
|
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
|
|||||||
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js
vendored
Normal file
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-advance-management.js
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/* eslint no-alert: 0 */
|
||||||
|
/* eslint consistent-return: 0 */
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
import Code from 'components/common/code-block';
|
||||||
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
|
const products = productsGenerator();
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
class AdvSelectionManagment extends React.Component {
|
||||||
|
handleOnSelect = (row, isSelect) => {
|
||||||
|
if (isSelect && row.id < 3) {
|
||||||
|
alert('Oops, You can not select Product ID which less than 3');
|
||||||
|
return false; // return false to deny current select action
|
||||||
|
}
|
||||||
|
return true; // return true or dont return to approve current select action
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnSelectAll = (isSelect, rows) => {
|
||||||
|
if (isSelect) {
|
||||||
|
return rows.filter(r => r.id >= 3).map(r => r.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
onSelect: this.handleOnSelect,
|
||||||
|
onSelectAll: this.handleOnSelectAll
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>You can not select Product ID less than 3</h3>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class AdvSelectionManagment extends React.Component {
|
||||||
|
handleOnSelect = (row, isSelect) => {
|
||||||
|
if (isSelect && row.id < 3) {
|
||||||
|
alert('Oops, You can not select Product ID which less than 3');
|
||||||
|
return false; // return false to deny current select action
|
||||||
|
}
|
||||||
|
return true; // return true or dont return to approve current select action
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnSelectAll = (isSelect, rows) => {
|
||||||
|
if (isSelect) {
|
||||||
|
return rows.filter(r => r.id >= 3).map(r => r.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const selectRow = {
|
||||||
|
mode: 'checkbox',
|
||||||
|
clickToSelect: true,
|
||||||
|
onSelect: this.handleOnSelect,
|
||||||
|
onSelectAll: this.handleOnSelectAll
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3>You can not select Product ID less than 3</h3>
|
||||||
|
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-example",
|
"name": "react-bootstrap-table2-example",
|
||||||
"version": "1.0.7",
|
"version": "1.0.11",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* eslint no-mixed-operators: 0 */
|
/* eslint no-mixed-operators: 0 */
|
||||||
|
/* eslint no-param-reassign: 0 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* products generator for stories
|
* products generator for stories
|
||||||
@@ -22,6 +23,12 @@ export const productsGenerator = (quantity = 5, callback) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const withOnSale = rows => rows.map((row) => {
|
||||||
|
if (row.id > 2) row.onSale = false;
|
||||||
|
else row.onSale = true;
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
|
||||||
export const productsQualityGenerator = (quantity = 5) =>
|
export const productsQualityGenerator = (quantity = 5) =>
|
||||||
Array.from({ length: quantity }, (value, index) => ({
|
Array.from({ length: quantity }, (value, index) => ({
|
||||||
id: index,
|
id: index,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import CustomFilterValue from 'examples/column-filter/custom-filter-value';
|
|||||||
import SelectFilter from 'examples/column-filter/select-filter';
|
import SelectFilter from 'examples/column-filter/select-filter';
|
||||||
import SelectFilterWithDefaultValue from 'examples/column-filter/select-filter-default-value';
|
import SelectFilterWithDefaultValue from 'examples/column-filter/select-filter-default-value';
|
||||||
import SelectFilterComparator from 'examples/column-filter/select-filter-like-comparator';
|
import SelectFilterComparator from 'examples/column-filter/select-filter-like-comparator';
|
||||||
|
import SelectFilterWithPreservedOptionsOrder from 'examples/column-filter/select-filter-preserve-option-order';
|
||||||
import CustomSelectFilter from 'examples/column-filter/custom-select-filter';
|
import CustomSelectFilter from 'examples/column-filter/custom-select-filter';
|
||||||
import MultiSelectFilter from 'examples/column-filter/multi-select-filter';
|
import MultiSelectFilter from 'examples/column-filter/multi-select-filter';
|
||||||
import MultiSelectFilterDefaultValue from 'examples/column-filter/multi-select-filter-default-value';
|
import MultiSelectFilterDefaultValue from 'examples/column-filter/multi-select-filter-default-value';
|
||||||
@@ -97,7 +98,9 @@ import RowLevelEditableTable from 'examples/cell-edit/row-level-editable-table';
|
|||||||
import ColumnLevelEditableTable from 'examples/cell-edit/column-level-editable-table';
|
import ColumnLevelEditableTable from 'examples/cell-edit/column-level-editable-table';
|
||||||
import CellLevelEditable from 'examples/cell-edit/cell-level-editable-table';
|
import CellLevelEditable from 'examples/cell-edit/cell-level-editable-table';
|
||||||
import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
|
import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
|
||||||
|
import AsyncCellEditHooks from 'examples/cell-edit/cell-edit-async-hooks-table';
|
||||||
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
|
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
|
||||||
|
import AsyncCellEditValidator from 'examples/cell-edit/cell-edit-async-validator-table';
|
||||||
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
|
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
|
||||||
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
|
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
|
||||||
import AutoSelectTextInput from 'examples/cell-edit/auto-select-text-input-table';
|
import AutoSelectTextInput from 'examples/cell-edit/auto-select-text-input-table';
|
||||||
@@ -116,6 +119,7 @@ import MultipleSelectionTable from 'examples/row-selection/multiple-selection';
|
|||||||
import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
||||||
import DefaultSelectTable from 'examples/row-selection/default-select';
|
import DefaultSelectTable from 'examples/row-selection/default-select';
|
||||||
import SelectionManagement from 'examples/row-selection/selection-management';
|
import SelectionManagement from 'examples/row-selection/selection-management';
|
||||||
|
import AdvanceSelectionManagement from 'examples/row-selection/selection-advance-management';
|
||||||
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
||||||
import SelectionWithExpansionTable from 'examples/row-selection/selection-with-expansion';
|
import SelectionWithExpansionTable from 'examples/row-selection/selection-with-expansion';
|
||||||
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
|
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
|
||||||
@@ -260,6 +264,7 @@ storiesOf('Column Filter', module)
|
|||||||
.add('Programmatically Multi Select Filter', () => <ProgrammaticallyMultiSelectFilter />)
|
.add('Programmatically Multi Select Filter', () => <ProgrammaticallyMultiSelectFilter />)
|
||||||
.add('Custom Filter', () => <CustomFilter />)
|
.add('Custom Filter', () => <CustomFilter />)
|
||||||
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
.add('Advance Custom Filter', () => <AdvanceCustomFilter />)
|
||||||
|
.add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
|
||||||
.add('Clear All Filters', () => <ClearAllFilters />);
|
.add('Clear All Filters', () => <ClearAllFilters />);
|
||||||
|
|
||||||
storiesOf('Work on Rows', module)
|
storiesOf('Work on Rows', module)
|
||||||
@@ -288,7 +293,9 @@ storiesOf('Cell Editing', module)
|
|||||||
.add('Column Level Editable', () => <ColumnLevelEditableTable />)
|
.add('Column Level Editable', () => <ColumnLevelEditableTable />)
|
||||||
.add('Cell Level Editable', () => <CellLevelEditable />)
|
.add('Cell Level Editable', () => <CellLevelEditable />)
|
||||||
.add('Rich Hook Functions', () => <CellEditHooks />)
|
.add('Rich Hook Functions', () => <CellEditHooks />)
|
||||||
|
.add('Async Hook Functions', () => <AsyncCellEditHooks />)
|
||||||
.add('Validation', () => <CellEditValidator />)
|
.add('Validation', () => <CellEditValidator />)
|
||||||
|
.add('Async Validation', () => <AsyncCellEditValidator />)
|
||||||
.add('Auto Select Text Input', () => <AutoSelectTextInput />)
|
.add('Auto Select Text Input', () => <AutoSelectTextInput />)
|
||||||
.add('Custom Cell Style', () => <CellEditStyleTable />)
|
.add('Custom Cell Style', () => <CellEditStyleTable />)
|
||||||
.add('Custom Cell Classes', () => <CellEditClassTable />)
|
.add('Custom Cell Classes', () => <CellEditClassTable />)
|
||||||
@@ -308,6 +315,7 @@ storiesOf('Row Selection', module)
|
|||||||
.add('Click to Select', () => <ClickToSelectTable />)
|
.add('Click to Select', () => <ClickToSelectTable />)
|
||||||
.add('Default Select', () => <DefaultSelectTable />)
|
.add('Default Select', () => <DefaultSelectTable />)
|
||||||
.add('Selection Management', () => <SelectionManagement />)
|
.add('Selection Management', () => <SelectionManagement />)
|
||||||
|
.add('Advance Selection Management', () => <AdvanceSelectionManagement />)
|
||||||
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
||||||
.add('Row Select and Expand', () => <SelectionWithExpansionTable />)
|
.add('Row Select and Expand', () => <SelectionWithExpansionTable />)
|
||||||
.add('Selection without Data', () => <SelectionNoDataTable />)
|
.add('Selection without Data', () => <SelectionNoDataTable />)
|
||||||
|
|||||||
@@ -115,6 +115,27 @@ const qualityFilter = selectFilter({
|
|||||||
// omit...
|
// omit...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Note, the selectOptions can be an array also:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const selectOptions = [
|
||||||
|
{ value: 0, label: 'good' },
|
||||||
|
{ value: 1, label: 'Bad' },
|
||||||
|
{ value: 2, label: 'unknown' }
|
||||||
|
];
|
||||||
|
const columns = [
|
||||||
|
..., {
|
||||||
|
dataField: 'quality',
|
||||||
|
text: 'Product Quailty',
|
||||||
|
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
|
||||||
|
filter: selectFilter({
|
||||||
|
options: selectOptions
|
||||||
|
})
|
||||||
|
}];
|
||||||
|
```
|
||||||
|
|
||||||
|
The benifit is `react-bootstrap-table2` will render the select options by the order of array.
|
||||||
|
|
||||||
## MultiSelect Filter
|
## MultiSelect Filter
|
||||||
|
|
||||||
A quick example:
|
A quick example:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-filter",
|
"name": "react-bootstrap-table2-filter",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"description": "it's a column filter addon for react-bootstrap-table2",
|
"description": "it's a column filter addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ import { LIKE, EQ } from '../comparison';
|
|||||||
import { FILTER_TYPE } from '../const';
|
import { FILTER_TYPE } from '../const';
|
||||||
|
|
||||||
function optionsEquals(currOpts, prevOpts) {
|
function optionsEquals(currOpts, prevOpts) {
|
||||||
|
if (Array.isArray(currOpts)) {
|
||||||
|
for (let i = 0; i < currOpts.length; i += 1) {
|
||||||
|
if (
|
||||||
|
currOpts[i].value !== prevOpts[i].value ||
|
||||||
|
currOpts[i].label !== prevOpts[i].label
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currOpts.length === prevOpts.length;
|
||||||
|
}
|
||||||
const keys = Object.keys(currOpts);
|
const keys = Object.keys(currOpts);
|
||||||
for (let i = 0; i < keys.length; i += 1) {
|
for (let i = 0; i < keys.length; i += 1) {
|
||||||
if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
|
if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
|
||||||
@@ -16,11 +27,21 @@ function optionsEquals(currOpts, prevOpts) {
|
|||||||
return Object.keys(currOpts).length === Object.keys(prevOpts).length;
|
return Object.keys(currOpts).length === Object.keys(prevOpts).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getOptionValue(options, key) {
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
const result = options
|
||||||
|
.filter(({ label }) => label === key)
|
||||||
|
.map(({ value }) => value);
|
||||||
|
return result[0];
|
||||||
|
}
|
||||||
|
return options[key];
|
||||||
|
}
|
||||||
|
|
||||||
class SelectFilter extends Component {
|
class SelectFilter extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.filter = this.filter.bind(this);
|
this.filter = this.filter.bind(this);
|
||||||
const isSelected = props.options[props.defaultValue] !== undefined;
|
const isSelected = getOptionValue(props.options, props.defaultValue) !== undefined;
|
||||||
this.state = { isSelected };
|
this.state = { isSelected };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +87,14 @@ class SelectFilter extends Component {
|
|||||||
<option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option>
|
<option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Object.keys(options).forEach(key =>
|
if (Array.isArray(options)) {
|
||||||
optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>)
|
options.forEach(({ value, label }) =>
|
||||||
);
|
optionTags.push(<option key={ value } value={ value }>{ label }</option>));
|
||||||
|
} else {
|
||||||
|
Object.keys(options).forEach(key =>
|
||||||
|
optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>)
|
||||||
|
);
|
||||||
|
}
|
||||||
return optionTags;
|
return optionTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +154,7 @@ class SelectFilter extends Component {
|
|||||||
SelectFilter.propTypes = {
|
SelectFilter.propTypes = {
|
||||||
onFilter: PropTypes.func.isRequired,
|
onFilter: PropTypes.func.isRequired,
|
||||||
column: PropTypes.object.isRequired,
|
column: PropTypes.object.isRequired,
|
||||||
options: PropTypes.object.isRequired,
|
options: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
|
||||||
comparator: PropTypes.oneOf([LIKE, EQ]),
|
comparator: PropTypes.oneOf([LIKE, EQ]),
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-paginator",
|
"name": "react-bootstrap-table2-paginator",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"description": "it's the pagination addon for react-bootstrap-table2",
|
"description": "it's the pagination addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
const PaginationTotal = props => (
|
const PaginationTotal = props => (
|
||||||
<span className="react-bootstrap-table-pagination-total">
|
<span className="react-bootstrap-table-pagination-total">
|
||||||
Showing rows { props.from } to { props.to + 1 } of { props.dataSize }
|
Showing rows { props.from } to { props.to } of { props.dataSize }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table-next",
|
"name": "react-bootstrap-table-next",
|
||||||
"version": "1.3.0",
|
"version": "1.4.2",
|
||||||
"description": "Next generation of react-bootstrap-table",
|
"description": "Next generation of react-bootstrap-table",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -15,13 +15,12 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
super(props);
|
super(props);
|
||||||
this.validateProps();
|
this.validateProps();
|
||||||
if (props.registerExposedAPI) {
|
if (props.registerExposedAPI) {
|
||||||
const getData = () => this.getData();
|
props.registerExposedAPI(this.getData);
|
||||||
props.registerExposedAPI(getData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exposed APIs
|
// Exposed APIs
|
||||||
getData = () => {
|
getData() {
|
||||||
return this.props.data;
|
return this.props.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,6 +45,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
tabIndexCell,
|
tabIndexCell,
|
||||||
id,
|
id,
|
||||||
classes,
|
classes,
|
||||||
|
bootstrap4,
|
||||||
striped,
|
striped,
|
||||||
hover,
|
hover,
|
||||||
bordered,
|
bordered,
|
||||||
@@ -67,7 +67,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
'table-striped': striped,
|
'table-striped': striped,
|
||||||
'table-hover': hover,
|
'table-hover': hover,
|
||||||
'table-bordered': bordered,
|
'table-bordered': bordered,
|
||||||
'table-condensed': condensed
|
[(bootstrap4 ? 'table-sm' : 'table-condensed')]: condensed
|
||||||
}, classes);
|
}, classes);
|
||||||
|
|
||||||
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
||||||
|
|||||||
@@ -7,17 +7,16 @@ const events = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default ExtendBase =>
|
export default ExtendBase =>
|
||||||
class RowEventDelegater extends ExtendBase {
|
class CellEventDelegater extends ExtendBase {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.clickNum = 0;
|
|
||||||
this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this);
|
this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
createDefaultEventHandler(cb) {
|
createDefaultEventHandler(cb) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
const { row, rowIndex } = this.props;
|
const { column, columnIndex } = this.props;
|
||||||
cb(e, row, rowIndex);
|
cb(e, column, columnIndex);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
5
packages/react-bootstrap-table2/src/cell.js
vendored
5
packages/react-bootstrap-table2/src/cell.js
vendored
@@ -2,9 +2,10 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import eventDelegater from './cell-event-delegater';
|
||||||
import _ from './utils';
|
import _ from './utils';
|
||||||
|
|
||||||
class Cell extends Component {
|
class Cell extends eventDelegater(Component) {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.handleEditingCell = this.handleEditingCell.bind(this);
|
this.handleEditingCell = this.handleEditingCell.bind(this);
|
||||||
@@ -73,7 +74,7 @@ class Cell extends Component {
|
|||||||
formatter,
|
formatter,
|
||||||
formatExtraData
|
formatExtraData
|
||||||
} = column;
|
} = column;
|
||||||
const attrs = { ...rest };
|
const attrs = this.delegate({ ...rest });
|
||||||
let content = column.isDummyField ? null : _.get(row, dataField);
|
let content = column.isDummyField ? null : _.get(row, dataField);
|
||||||
|
|
||||||
if (formatter) {
|
if (formatter) {
|
||||||
|
|||||||
@@ -43,20 +43,24 @@ class SelectionProvider extends React.Component {
|
|||||||
|
|
||||||
let currSelected = [...this.state.selected];
|
let currSelected = [...this.state.selected];
|
||||||
|
|
||||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
let result = true;
|
||||||
currSelected = [rowKey];
|
|
||||||
} else if (checked) { // when select mode is checkbox
|
|
||||||
currSelected.push(rowKey);
|
|
||||||
} else {
|
|
||||||
currSelected = currSelected.filter(value => value !== rowKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onSelect) {
|
if (onSelect) {
|
||||||
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||||
onSelect(row, checked, rowIndex, e);
|
result = onSelect(row, checked, rowIndex, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(() => ({ selected: currSelected }));
|
this.setState(() => {
|
||||||
|
if (result === true || result === undefined) {
|
||||||
|
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||||
|
currSelected = [rowKey];
|
||||||
|
} else if (checked) { // when select mode is checkbox
|
||||||
|
currSelected.push(rowKey);
|
||||||
|
} else {
|
||||||
|
currSelected = currSelected.filter(value => value !== rowKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { selected: currSelected };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAllRowsSelect = (e, isUnSelect) => {
|
handleAllRowsSelect = (e, isUnSelect) => {
|
||||||
@@ -78,8 +82,9 @@ class SelectionProvider extends React.Component {
|
|||||||
currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
|
currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let result;
|
||||||
if (onSelectAll) {
|
if (onSelectAll) {
|
||||||
onSelectAll(
|
result = onSelectAll(
|
||||||
!isUnSelect,
|
!isUnSelect,
|
||||||
dataOperator.getSelectedRows(
|
dataOperator.getSelectedRows(
|
||||||
data,
|
data,
|
||||||
@@ -88,8 +93,10 @@ class SelectionProvider extends React.Component {
|
|||||||
),
|
),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
|
if (Array.isArray(result)) {
|
||||||
|
currSelected = result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(() => ({ selected: currSelected }));
|
this.setState(() => ({ selected: currSelected }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ const Header = (props) => {
|
|||||||
sortOrder,
|
sortOrder,
|
||||||
selectRow,
|
selectRow,
|
||||||
onExternalFilter,
|
onExternalFilter,
|
||||||
expandRow,
|
expandRow
|
||||||
bootstrap4
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
let SelectionHeaderCellComp = () => null;
|
let SelectionHeaderCellComp = () => null;
|
||||||
@@ -50,7 +49,6 @@ const Header = (props) => {
|
|||||||
return (
|
return (
|
||||||
<HeaderCell
|
<HeaderCell
|
||||||
index={ i }
|
index={ i }
|
||||||
bootstrap4={ bootstrap4 }
|
|
||||||
key={ column.dataField }
|
key={ column.dataField }
|
||||||
column={ column }
|
column={ column }
|
||||||
onSort={ onSort }
|
onSort={ onSort }
|
||||||
@@ -78,8 +76,7 @@ Header.propTypes = {
|
|||||||
selectRow: PropTypes.object,
|
selectRow: PropTypes.object,
|
||||||
onExternalFilter: PropTypes.func,
|
onExternalFilter: PropTypes.func,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
expandRow: PropTypes.object,
|
expandRow: PropTypes.object
|
||||||
bootstrap4: PropTypes.bool
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Header;
|
export default Header;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default class ExpandCell extends Component {
|
|||||||
|
|
||||||
handleClick(e) {
|
handleClick(e) {
|
||||||
const { rowKey, expanded, onRowExpand, rowIndex } = this.props;
|
const { rowKey, expanded, onRowExpand, rowIndex } = this.props;
|
||||||
|
e.stopPropagation();
|
||||||
onRowExpand(rowKey, !expanded, rowIndex, e);
|
onRowExpand(rowKey, !expanded, rowIndex, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,13 +50,21 @@ export default class RowPureContent extends React.Component {
|
|||||||
// render cell
|
// render cell
|
||||||
let cellTitle;
|
let cellTitle;
|
||||||
let cellStyle = {};
|
let cellStyle = {};
|
||||||
const cellAttrs = {
|
let cellAttrs = {
|
||||||
..._.isFunction(column.attrs)
|
..._.isFunction(column.attrs)
|
||||||
? column.attrs(content, row, rowIndex, index)
|
? column.attrs(content, row, rowIndex, index)
|
||||||
: column.attrs,
|
: column.attrs
|
||||||
...column.events
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (column.events) {
|
||||||
|
const events = Object.assign({}, column.events);
|
||||||
|
Object.keys(Object.assign({}, column.events)).forEach((key) => {
|
||||||
|
const originFn = events[key];
|
||||||
|
events[key] = (...rest) => originFn(...rest, row, rowIndex);
|
||||||
|
});
|
||||||
|
cellAttrs = { ...cellAttrs, ...events };
|
||||||
|
}
|
||||||
|
|
||||||
const cellClasses = _.isFunction(column.classes)
|
const cellClasses = _.isFunction(column.classes)
|
||||||
? column.classes(content, row, rowIndex, index)
|
? column.classes(content, row, rowIndex, index)
|
||||||
: column.classes;
|
: column.classes;
|
||||||
|
|||||||
Reference in New Issue
Block a user