Compare commits

...

42 Commits

Author SHA1 Message Date
AllenFang
d3161f02eb Publish
- react-bootstrap-table2-example@1.0.12
 - react-bootstrap-table-next@1.4.3
2018-12-21 16:51:04 +08:00
Allen
28ba6d5677 Merge pull request #721 from react-bootstrap-table/develop
20181221 release
2018-12-21 16:49:35 +08:00
AllenFang
4ddbfd4972 fix #711 2018-12-21 16:23:38 +08:00
AllenFang
d84dc46ff1 Merge branch 'vinzentt-fix-nonExpandable-indicator-and-behaviour' into develop 2018-12-20 23:52:42 +08:00
AllenFang
e0163625d4 add expandable for expandColumnRenderer 2018-12-20 23:47:30 +08:00
AllenFang
24ab58a464 row expandable already calculated from row expand consumer, just use it instead do the logic again 2018-12-20 23:45:20 +08:00
Allen
6e19368733 Merge branch 'develop' into fix-nonExpandable-indicator-and-behaviour 2018-12-20 23:27:48 +08:00
AllenFang
bc4697bf95 fix #701 2018-12-20 23:20:12 +08:00
AllenFang
9d2a6a1b23 Publish
- react-bootstrap-table2-example@1.0.11
 - react-bootstrap-table-next@1.4.2
2018-12-05 23:31:35 +08:00
Allen
bb752fcec8 Merge pull request #699 from react-bootstrap-table/develop
20181205 release
2018-12-05 23:30:19 +08:00
Vincent Degroote
aedd1f5942 Add expandColumn in storybook example for nonExpandable rows 2018-12-05 11:37:32 +01:00
Vincent Degroote
5a5f10f609 fix tests when nonExpndable is not given 2018-12-05 11:23:38 +01:00
Vincent Degroote
e041a3d736 revert not needed changes 2018-12-05 10:55:04 +01:00
Vincent Degroote
f175fd4186 Hide expand indicator if row is not expandable and prevent it from being expanded 2018-12-05 10:50:52 +01:00
AllenFang
5a6b7e122d fix #680 2018-12-02 17:45:42 +08:00
AllenFang
a7ae524c49 fix #675 2018-12-02 17:29:25 +08:00
AllenFang
a23599f52f fix #669 2018-12-02 17:04:32 +08:00
EricH
c50853b16d Fix typo in doc example code (#691) 2018-12-02 15:48:52 +08:00
NickChen
3f74542c98 Merge pull request #670 from react-bootstrap-table/enhancement/remove-unnecessary-props-bootstrap4
LGTM
2018-11-18 18:04:24 +08:00
Chun-MingChen
47aa41b8fa Remove unnecessary props 'bootstrap4' 2018-11-18 17:55:27 +08:00
AllenFang
67ed2e6c80 Publish
- react-bootstrap-table2-editor@1.2.2
 - react-bootstrap-table2-example@1.0.10
 - react-bootstrap-table2-filter@1.1.0
 - react-bootstrap-table2-paginator@1.0.4
 - react-bootstrap-table-next@1.4.1
2018-11-10 17:19:43 +08:00
Allen
794a97956d Merge pull request #661 from react-bootstrap-table/develop
20181110 release
2018-11-10 17:18:11 +08:00
AllenFang
78ca01bb1a fix #582 2018-11-10 16:58:02 +08:00
Yassien
b79dbc80f6 Condensed now takes bootstrap4 into consideration (#653) 2018-11-10 15:55:54 +08:00
AllenFang
3f21a67620 Merge branch 'develop' of https://github.com/react-bootstrap-table/react-bootstrap-table2 into develop 2018-11-10 15:54:10 +08:00
AllenFang
9e3ae385ce Merge branch 'jehartzog-fix-select-filter-typo' into develop 2018-11-10 15:53:43 +08:00
AllenFang
c6ea19fe8a enhance for #649 2018-11-10 15:53:20 +08:00
AllenFang
a5b42dca92 Merge branch 'fix-select-filter-typo' of https://github.com/jehartzog/react-bootstrap-table2 into jehartzog-fix-select-filter-typo 2018-11-10 15:45:08 +08:00
Joshua
28f3c33db3 Update README.md (#658)
* Update README.md

* Address review comment

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

* Use being instead of is

Co-Authored-By: konekoya <tank158r5155@yahoo.com.tw>
2018-11-10 15:43:23 +08:00
Allen
2530a70c00 fix #654 #611 (#660) 2018-11-10 15:42:59 +08:00
AllenFang
569dd61463 fix #655 2018-11-10 13:55:46 +08:00
EricH
68264b45ce fix #641 typo 2018-11-05 07:09:39 -07:00
AllenFang
e251068657 Publish
- react-bootstrap-table2-example@1.0.9
 - react-bootstrap-table2-filter@1.0.2
 - react-bootstrap-table-next@1.4.0
2018-11-05 00:11:59 +08:00
Allen
e4fbb284b4 Merge pull request #647 from react-bootstrap-table/develop
20181104 release
2018-11-05 00:04:22 +08:00
Allen
a6afc9d9a8 Merge pull request #646 from react-bootstrap-table/enhance/641
Enhance/641
2018-11-04 16:44:11 +08:00
AllenFang
a0ba41c103 patch docs for #641 2018-11-04 16:32:13 +08:00
AllenFang
4a16cb314d add story for #641 2018-11-04 16:24:48 +08:00
AllenFang
98a04a5710 fix #641 2018-11-04 16:24:34 +08:00
Allen
c22a2a1d71 Merge pull request #644 from react-bootstrap-table/enhance/297
Enhance/297
2018-11-03 17:58:22 +08:00
AllenFang
9bc25c9d3e patch docs for selection control 2018-11-03 16:45:05 +08:00
AllenFang
4554db02d2 add story for advance selection contrl 2018-11-03 16:37:51 +08:00
AllenFang
b7fac973d2 fix #297 2018-11-03 16:37:02 +08:00
31 changed files with 458 additions and 59 deletions

View File

@@ -1,43 +1,56 @@
# react-bootstrap-table2 # react-bootstrap-table2
[![Build Status](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2.svg?branch=master)](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2) [![Build Status](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2.svg?branch=master)](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2)
Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) Rebuilt of [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
> `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to some guys already used it > Note that `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to the name being already taken.
`react-bootstrap-table2` separate some functionalities from core modules to other modules like following: `react-bootstrap-table2` separates some functionalities from its core modules to other modules as listed in the following:
* [`react-bootstrap-table-next`](https://www.npmjs.com/package/react-bootstrap-table-next) - [`react-bootstrap-table-next`](https://www.npmjs.com/package/react-bootstrap-table-next)
* [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter) - [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter)
* [`react-bootstrap-table2-editor`](https://www.npmjs.com/package/react-bootstrap-table2-editor) - [`react-bootstrap-table2-editor`](https://www.npmjs.com/package/react-bootstrap-table2-editor)
* [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator) - [`react-bootstrap-table2-paginator`](https://www.npmjs.com/package/react-bootstrap-table2-paginator)
* [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay) - [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay)
* [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit) - [`react-bootstrap-table2-toolkit`](https://www.npmjs.com/package/react-bootstrap-table2-toolkit)
This can help your application with less bundled size and also help us have clean design to avoid handling to much logic in kernel module(SRP). Not only does this reduce the bundle size of your apps but also helps us have a cleaner design to avoid handling too much logic in the kernel module(SRP).
## Migration ## Migration
If you are the user from legacy [`react-bootstrap-table`](https://github.com/AllenFang/react-bootstrap-table/), please have a look on [this](./docs/migration.md).
If you are coming from the legacy [`react-bootstrap-table`](https://github.com/AllenFang/react-bootstrap-table/), please check out the [migration guide](./docs/migration.md).
## Usage ## Usage
See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html). See [getting started](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/getting-started.html).
## Online Demo ## Online Demo
See `react-bootstrap-table2` [storybook](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html). See `react-bootstrap-table2` [storybook](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html).
## Roadmap ## 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)**

View File

@@ -27,6 +27,7 @@
* [rowStyle](#rowStyle) * [rowStyle](#rowStyle)
* [rowClasses](#rowClasses) * [rowClasses](#rowClasses)
* [rowEvents](#rowEvents) * [rowEvents](#rowEvents)
* [hiddenRows](#hiddenRows)
* [defaultSorted](#defaultSorted) * [defaultSorted](#defaultSorted)
* [defaultSortDirection](#defaultSortDirection) * [defaultSortDirection](#defaultSortDirection)
* [pagination](#pagination) * [pagination](#pagination)
@@ -181,6 +182,14 @@ const rowEvents = {
<BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } /> <BootstrapTable data={ data } columns={ columns } rowEvents={ rowEvents } />
``` ```
### <a name='hiddenRows'>hiddenRows - [Array]</a>
Hide rows, this props accept an array of row keys:
```js
const hiddenRows = [1, 4];
<BootstrapTable data={ data } columns={ columns } hiddenRows={ hiddenRows } />
```
### <a name='defaultSorted'>defaultSorted - [Array]</a> ### <a name='defaultSorted'>defaultSorted - [Array]</a>
`defaultSorted` accept an object array which allow you to define the default sort columns when first render. `defaultSorted` accept an object array which allow you to define the default sort columns when first render.

View File

@@ -92,13 +92,16 @@ const expandRow = {
``` ```
### <a name='expandColumnRenderer'>expandRow.expandColumnRenderer - [Function]</a> ### <a name='expandColumnRenderer'>expandRow.expandColumnRenderer - [Function]</a>
Provide a callback function which allow you to custom the expand indicator. This callback only have one argument which is an object and contain one property `expanded` which indicate if current row is expanded Provide a callback function which allow you to custom the expand indicator. This callback only have one argument which is an object and contain these properties:
* `expanded`: If current row is expanded or not
* `rowKey`: Current row key
* `expandable`: If currnet row is expandable or not
```js ```js
const expandRow = { const expandRow = {
renderer: (row) => ... renderer: (row) => ...
expandColumnRenderer: ({ expanded }) => ( expandColumnRenderer: ({ expanded, rowKey, expandable }) => (
// .... // ....
) )
}; };

View File

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

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-editor", "name": "react-bootstrap-table2-editor",
"version": "1.2.1", "version": "1.2.2",
"description": "it's the editor addon for react-bootstrap-table2", "description": "it's the editor addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"scripts": { "scripts": {

View File

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
const EditorIndicator = ({ invalidMessage }) => const EditorIndicator = ({ invalidMessage }) =>
( (
<div className="alert alert-danger fade in"> <div className="alert alert-danger in" role="alert">
<strong>{ invalidMessage }</strong> <strong>{ invalidMessage }</strong>
</div> </div>
); );

View File

@@ -103,7 +103,7 @@ const columns = [{
}, { }, {
dataField: 'quality', dataField: 'quality',
text: 'Product Quality', text: 'Product Quality',
editorRenderer: (editorProps, value, row, rowIndex, columnIndex) => ( editorRenderer: (editorProps, value, row, column, rowIndex, columnIndex) => (
<QualityRanger { ...editorProps } value={ value } /> <QualityRanger { ...editorProps } value={ value } />
) )
}]; }];

View File

@@ -0,0 +1,70 @@
/* eslint max-len: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block';
import { productsQualityGenerator } from 'utils/common';
const products = productsQualityGenerator(6);
const selectOptions = [
{ value: 0, label: 'good' },
{ value: 1, label: 'Bad' },
{ value: 2, label: 'unknown' }
];
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
filter: selectFilter({
options: selectOptions
})
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter';
const selectOptions = [
{ value: 0, label: 'good' },
{ value: 1, label: 'Bad' },
{ value: 2, label: 'unknown' }
];
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
filter: selectFilter({
options: selectOptions
})
}];
<BootstrapTable keyField='id' data={ products } columns={ columns } filter={ filterFactory() } />
`;
export default () => (
<div>
<h3><code>selectFilter.options</code> accept an Array and we keep that order when rendering the options</h3>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);

View File

@@ -2,9 +2,9 @@ import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block'; import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common'; import { productsGenerator, withOnSale } from 'utils/common';
const products = productsGenerator(); const products = withOnSale(productsGenerator());
function priceFormatter(cell, row) { function priceFormatter(cell, row) {
if (row.onSale) { if (row.onSale) {

View File

@@ -1,4 +1,5 @@
/* eslint react/prop-types: 0 */ /* eslint react/prop-types: 0 */
/* eslint no-unused-vars: 0 */
import React from 'react'; import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
@@ -33,7 +34,7 @@ const expandRow = {
} }
return <b>+</b>; return <b>+</b>;
}, },
expandColumnRenderer: ({ expanded }) => { expandColumnRenderer: ({ expanded, rowKey, expandable }) => {
if (expanded) { if (expanded) {
return ( return (
<b>-</b> <b>-</b>

View File

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

View File

@@ -25,6 +25,7 @@ const expandRow = {
<p>expandRow.renderer callback will pass the origin row object to you</p> <p>expandRow.renderer callback will pass the origin row object to you</p>
</div> </div>
), ),
showExpandColumn: true,
nonExpandable: [1, 3] nonExpandable: [1, 3]
}; };
@@ -50,6 +51,7 @@ const expandRow = {
<p>expandRow.renderer callback will pass the origin row object to you</p> <p>expandRow.renderer callback will pass the origin row object to you</p>
</div> </div>
), ),
showExpandColumn: true,
nonExpandable: [1, 3] nonExpandable: [1, 3]
}; };

View File

@@ -0,0 +1,88 @@
/* eslint no-alert: 0 */
/* eslint consistent-return: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
class AdvSelectionManagment extends React.Component {
handleOnSelect = (row, isSelect) => {
if (isSelect && row.id < 3) {
alert('Oops, You can not select Product ID which less than 3');
return false; // return false to deny current select action
}
return true; // return true or dont return to approve current select action
}
handleOnSelectAll = (isSelect, rows) => {
if (isSelect) {
return rows.filter(r => r.id >= 3).map(r => r.id);
}
}
render() {
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
onSelect: this.handleOnSelect,
onSelectAll: this.handleOnSelectAll
};
return (
<div>
<h3>You can not select Product ID less than 3</h3>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);
}
}
`;
export default class AdvSelectionManagment extends React.Component {
handleOnSelect = (row, isSelect) => {
if (isSelect && row.id < 3) {
alert('Oops, You can not select Product ID which less than 3');
return false; // return false to deny current select action
}
return true; // return true or dont return to approve current select action
}
handleOnSelectAll = (isSelect, rows) => {
if (isSelect) {
return rows.filter(r => r.id >= 3).map(r => r.id);
}
}
render() {
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
onSelect: this.handleOnSelect,
onSelectAll: this.handleOnSelectAll
};
return (
<div>
<h3>You can not select Product ID less than 3</h3>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);
}
}

View File

@@ -0,0 +1,57 @@
/* eslint no-unused-vars: 0 */
/* eslint no-console: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const rowEvents = {
onClick: (e, row, rowIndex) => {
console.log(`clicked on row with index: ${rowIndex}`);
},
onMouseEnter: (e, row, rowIndex) => {
console.log(`enter on row with index: ${rowIndex}`);
}
};
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const hiddenRowKeys = [1, 3];
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
`;
const hiddenRowKeys = [1, 3];
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
<Code>{ sourceCode }</Code>
</div>
);

View File

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

View File

@@ -1,4 +1,5 @@
/* eslint no-mixed-operators: 0 */ /* eslint no-mixed-operators: 0 */
/* eslint no-param-reassign: 0 */
/** /**
* products generator for stories * products generator for stories
@@ -22,6 +23,12 @@ export const productsGenerator = (quantity = 5, callback) => {
); );
}; };
export const withOnSale = rows => rows.map((row) => {
if (row.id > 2) row.onSale = false;
else row.onSale = true;
return row;
});
export const productsQualityGenerator = (quantity = 5) => export const productsQualityGenerator = (quantity = 5) =>
Array.from({ length: quantity }, (value, index) => ({ Array.from({ length: quantity }, (value, index) => ({
id: index, id: index,

View File

@@ -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';
@@ -78,6 +79,7 @@ import ClearAllFilters from 'examples/column-filter/clear-all-filters';
import RowStyleTable from 'examples/rows/row-style'; import RowStyleTable from 'examples/rows/row-style';
import RowClassTable from 'examples/rows/row-class'; import RowClassTable from 'examples/rows/row-class';
import RowEventTable from 'examples/rows/row-event'; import RowEventTable from 'examples/rows/row-event';
import RowHiddenTable from 'examples/rows/row-hidden';
// table sort // table sort
import EnableSortTable from 'examples/sort/enable-sort-table'; import EnableSortTable from 'examples/sort/enable-sort-table';
@@ -118,6 +120,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';
@@ -262,12 +265,14 @@ storiesOf('Column Filter', module)
.add('Programmatically Multi Select Filter', () => <ProgrammaticallyMultiSelectFilter />) .add('Programmatically Multi Select Filter', () => <ProgrammaticallyMultiSelectFilter />)
.add('Custom Filter', () => <CustomFilter />) .add('Custom Filter', () => <CustomFilter />)
.add('Advance Custom Filter', () => <AdvanceCustomFilter />) .add('Advance Custom Filter', () => <AdvanceCustomFilter />)
.add('Preserved Option Order on Select Filter', () => <SelectFilterWithPreservedOptionsOrder />)
.add('Clear All Filters', () => <ClearAllFilters />); .add('Clear All Filters', () => <ClearAllFilters />);
storiesOf('Work on Rows', module) storiesOf('Work on Rows', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Customize Row Style', () => <RowStyleTable />) .add('Customize Row Style', () => <RowStyleTable />)
.add('Customize Row Class', () => <RowClassTable />) .add('Customize Row Class', () => <RowClassTable />)
.add('Hide Rows', () => <RowHiddenTable />)
.add('Row Event', () => <RowEventTable />); .add('Row Event', () => <RowEventTable />);
storiesOf('Sort Table', module) storiesOf('Sort Table', module)
@@ -312,6 +317,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 />)

View File

@@ -115,6 +115,27 @@ const qualityFilter = selectFilter({
// omit... // omit...
``` ```
> Note, the selectOptions can be an array also:
```js
const selectOptions = [
{ value: 0, label: 'good' },
{ value: 1, label: 'Bad' },
{ value: 2, label: 'unknown' }
];
const columns = [
..., {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions.find(opt => opt.value === cell).label,
filter: selectFilter({
options: selectOptions
})
}];
```
The benifit is `react-bootstrap-table2` will render the select options by the order of array.
## MultiSelect Filter ## MultiSelect Filter
A quick example: A quick example:

View File

@@ -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": {

View File

@@ -7,6 +7,17 @@ import { LIKE, EQ } from '../comparison';
import { FILTER_TYPE } from '../const'; import { FILTER_TYPE } from '../const';
function optionsEquals(currOpts, prevOpts) { function optionsEquals(currOpts, prevOpts) {
if (Array.isArray(currOpts)) {
for (let i = 0; i < currOpts.length; i += 1) {
if (
currOpts[i].value !== prevOpts[i].value ||
currOpts[i].label !== prevOpts[i].label
) {
return false;
}
}
return currOpts.length === prevOpts.length;
}
const keys = Object.keys(currOpts); const keys = Object.keys(currOpts);
for (let i = 0; i < keys.length; i += 1) { for (let i = 0; i < keys.length; i += 1) {
if (currOpts[keys[i]] !== prevOpts[keys[i]]) { if (currOpts[keys[i]] !== prevOpts[keys[i]]) {
@@ -16,11 +27,21 @@ function optionsEquals(currOpts, prevOpts) {
return Object.keys(currOpts).length === Object.keys(prevOpts).length; return Object.keys(currOpts).length === Object.keys(prevOpts).length;
} }
function getOptionValue(options, key) {
if (Array.isArray(options)) {
const result = options
.filter(({ label }) => label === key)
.map(({ value }) => value);
return result[0];
}
return options[key];
}
class SelectFilter extends Component { class SelectFilter extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.filter = this.filter.bind(this); this.filter = this.filter.bind(this);
const isSelected = props.options[props.defaultValue] !== undefined; const isSelected = getOptionValue(props.options, props.defaultValue) !== undefined;
this.state = { isSelected }; this.state = { isSelected };
} }
@@ -66,9 +87,14 @@ class SelectFilter extends Component {
<option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option> <option key="-1" value="">{ placeholder || `Select ${column.text}...` }</option>
)); ));
} }
if (Array.isArray(options)) {
options.forEach(({ value, label }) =>
optionTags.push(<option key={ value } value={ value }>{ label }</option>));
} else {
Object.keys(options).forEach(key => Object.keys(options).forEach(key =>
optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>) optionTags.push(<option key={ key } value={ key }>{ options[key] }</option>)
); );
}
return optionTags; return optionTags;
} }
@@ -128,7 +154,7 @@ class SelectFilter extends Component {
SelectFilter.propTypes = { SelectFilter.propTypes = {
onFilter: PropTypes.func.isRequired, onFilter: PropTypes.func.isRequired,
column: PropTypes.object.isRequired, column: PropTypes.object.isRequired,
options: PropTypes.object.isRequired, options: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
comparator: PropTypes.oneOf([LIKE, EQ]), comparator: PropTypes.oneOf([LIKE, EQ]),
placeholder: PropTypes.string, placeholder: PropTypes.string,
style: PropTypes.object, style: PropTypes.object,

View File

@@ -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": {

View File

@@ -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">
&nbsp;Showing rows { props.from } to&nbsp;{ props.to + 1 } of&nbsp;{ props.dataSize } &nbsp;Showing rows { props.from } to&nbsp;{ props.to } of&nbsp;{ props.dataSize }
</span> </span>
); );

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table-next", "name": "react-bootstrap-table-next",
"version": "1.3.1", "version": "1.4.3",
"description": "Next generation of react-bootstrap-table", "description": "Next generation of react-bootstrap-table",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {

View File

@@ -21,7 +21,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
// Exposed APIs // Exposed APIs
getData() { getData() {
return this.props.data; return this.visibleRows();
} }
render() { render() {
@@ -39,12 +39,12 @@ class BootstrapTable extends PropsBaseResolver(Component) {
renderTable() { renderTable() {
const { const {
data,
columns, columns,
keyField, keyField,
tabIndexCell, tabIndexCell,
id, id,
classes, classes,
bootstrap4,
striped, striped,
hover, hover,
bordered, bordered,
@@ -66,7 +66,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>);
@@ -87,7 +87,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
expandRow={ expandRow } expandRow={ expandRow }
/> />
<Body <Body
data={ data } data={ this.getData() }
keyField={ keyField } keyField={ keyField }
tabIndexCell={ tabIndexCell } tabIndexCell={ tabIndexCell }
columns={ columns } columns={ columns }

View File

@@ -23,6 +23,9 @@ class RowExpandProvider extends React.Component {
} }
handleRowExpand = (rowKey, expanded, rowIndex, e) => { handleRowExpand = (rowKey, expanded, rowIndex, e) => {
if (this.props.expandRow.nonExpandable.includes(rowKey)) {
return;
}
const { data, keyField, expandRow: { onExpand, onlyOneExpanding } } = this.props; const { data, keyField, expandRow: { onExpand, onlyOneExpanding } } = this.props;
let currExpanded = [...this.state.expanded]; let currExpanded = [...this.state.expanded];
@@ -73,6 +76,7 @@ class RowExpandProvider extends React.Component {
<RowExpandContext.Provider <RowExpandContext.Provider
value={ { value={ {
...this.props.expandRow, ...this.props.expandRow,
nonExpandable: this.props.expandRow.nonExpandable,
expanded: this.state.expanded, expanded: this.state.expanded,
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded), isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
onRowExpand: this.handleRowExpand, onRowExpand: this.handleRowExpand,

View File

@@ -43,6 +43,14 @@ class SelectionProvider extends React.Component {
let currSelected = [...this.state.selected]; let currSelected = [...this.state.selected];
let result = true;
if (onSelect) {
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
result = onSelect(row, checked, rowIndex, e);
}
this.setState(() => {
if (result === true || result === undefined) {
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
currSelected = [rowKey]; currSelected = [rowKey];
} else if (checked) { // when select mode is checkbox } else if (checked) { // when select mode is checkbox
@@ -50,13 +58,9 @@ class SelectionProvider extends React.Component {
} else { } else {
currSelected = currSelected.filter(value => value !== rowKey); currSelected = currSelected.filter(value => value !== rowKey);
} }
if (onSelect) {
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
onSelect(row, checked, rowIndex, e);
} }
return { selected: currSelected };
this.setState(() => ({ 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 }));
} }

View File

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

View File

@@ -1,3 +1,4 @@
import _ from '../utils';
import ColumnResolver from './column-resolver'; import ColumnResolver from './column-resolver';
export default ExtendBase => export default ExtendBase =>
@@ -15,4 +16,13 @@ export default ExtendBase =>
isEmpty() { isEmpty() {
return this.props.data.length === 0; return this.props.data.length === 0;
} }
visibleRows() {
const { data, hiddenRows, keyField } = this.props;
if (!hiddenRows || hiddenRows.length === 0) return data;
return data.filter((row) => {
const key = _.get(row, keyField);
return !hiddenRows.includes(key);
});
}
}; };

View File

@@ -10,6 +10,7 @@ export default class ExpandCell extends Component {
static propTypes = { static propTypes = {
rowKey: PropTypes.any, rowKey: PropTypes.any,
expanded: PropTypes.bool.isRequired, expanded: PropTypes.bool.isRequired,
expandable: PropTypes.bool.isRequired,
onRowExpand: PropTypes.func.isRequired, onRowExpand: PropTypes.func.isRequired,
expandColumnRenderer: PropTypes.func, expandColumnRenderer: PropTypes.func,
rowIndex: PropTypes.number, rowIndex: PropTypes.number,
@@ -33,12 +34,12 @@ 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);
} }
render() { render() {
const { expanded, expandColumnRenderer, tabIndex } = this.props; const { expanded, expandable, expandColumnRenderer, tabIndex, rowKey } = this.props;
const attrs = {}; const attrs = {};
if (tabIndex !== -1) attrs.tabIndex = tabIndex; if (tabIndex !== -1) attrs.tabIndex = tabIndex;
@@ -46,8 +47,10 @@ export default class ExpandCell extends Component {
<td onClick={ this.handleClick } { ...attrs }> <td onClick={ this.handleClick } { ...attrs }>
{ {
expandColumnRenderer ? expandColumnRenderer({ expandColumnRenderer ? expandColumnRenderer({
expanded expandable,
}) : (expanded ? '(-)' : '(+)') expanded,
rowKey
}) : (expandable ? (expanded ? '(-)' : '(+)') : '')
} }
</td> </td>
); );

View File

@@ -31,6 +31,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
if ( if (
this.props.selected !== nextProps.selected || this.props.selected !== nextProps.selected ||
this.props.expanded !== nextProps.expanded || this.props.expanded !== nextProps.expanded ||
this.props.expandable !== nextProps.expandable ||
this.props.selectable !== nextProps.selectable || this.props.selectable !== nextProps.selectable ||
this.shouldUpdatedBySelfProps(nextProps) this.shouldUpdatedBySelfProps(nextProps)
) { ) {
@@ -54,6 +55,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
selectRow, selectRow,
expandRow, expandRow,
expanded, expanded,
expandable,
selected, selected,
selectable, selectable,
visibleColumnSize, visibleColumnSize,
@@ -84,6 +86,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
rowKey={ key } rowKey={ key }
rowIndex={ rowIndex } rowIndex={ rowIndex }
expanded={ expanded } expanded={ expanded }
expandable={ expandable }
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 } tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
/> />
) : null ) : null

View File

@@ -25,6 +25,51 @@ describe('TableResolver', () => {
const BootstrapTableMock = extendTo(ExtendBase); const BootstrapTableMock = extendTo(ExtendBase);
let wrapper; let wrapper;
describe('visibleRows', () => {
describe('if hiddenRows prop is not existing', () => {
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns, keyField
}, null);
wrapper = shallow(mockElement);
});
it('should return correct data', () => {
expect(wrapper.instance().visibleRows()).toEqual(data);
});
});
describe('if hiddenRows prop is an empty array', () => {
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns, keyField, hiddenRows: []
}, null);
wrapper = shallow(mockElement);
});
it('should return correct data', () => {
expect(wrapper.instance().visibleRows()).toEqual(data);
});
});
describe('if hiddenRows prop is not an empty array', () => {
const hiddenRows = [1];
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns, keyField, hiddenRows
}, null);
wrapper = shallow(mockElement);
});
it('should return correct data', () => {
const result = wrapper.instance().visibleRows();
expect(result).toHaveLength(data.length - hiddenRows.length);
expect(result).toEqual(data.filter(d => !hiddenRows.includes(d.id)));
});
});
});
describe('validateProps', () => { describe('validateProps', () => {
describe('if keyField is defined and columns is all visible', () => { describe('if keyField is defined and columns is all visible', () => {
beforeEach(() => { beforeEach(() => {