mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-30 06:00:13 +00:00
Compare commits
4 Commits
react-boot
...
feature/st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f49c41cab1 | ||
|
|
6ff2ba35b4 | ||
|
|
53bdd2e3a0 | ||
|
|
26e2cb4077 |
41
README.md
41
README.md
@@ -1,56 +1,43 @@
|
|||||||
# 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 of [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
|
Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table)
|
||||||
|
|
||||||
> 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`'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
|
||||||
|
|
||||||
`react-bootstrap-table2` separates some functionalities from its core modules to other modules as listed in the following:
|
`react-bootstrap-table2` separate some functionalities from core modules to other modules like 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)
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
## 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).
|
||||||
|
|
||||||
Please check the [development guide](./docs/development.md).
|
## How should I run storybook example in my local?
|
||||||
|
|
||||||
## 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)**
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
* [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)
|
||||||
@@ -182,14 +181,6 @@ 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.
|
||||||
|
|
||||||
|
|||||||
@@ -92,16 +92,13 @@ 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 these properties:
|
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
|
||||||
* `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, rowKey, expandable }) => (
|
expandColumnRenderer: ({ expanded }) => (
|
||||||
// ....
|
// ....
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -211,44 +211,18 @@ 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, rows, e) => {
|
onSelectAll: (isSelect, results, 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.2",
|
"version": "1.2.1",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
const EditorIndicator = ({ invalidMessage }) =>
|
const EditorIndicator = ({ invalidMessage }) =>
|
||||||
(
|
(
|
||||||
<div className="alert alert-danger in" role="alert">
|
<div className="alert alert-danger fade in">
|
||||||
<strong>{ invalidMessage }</strong>
|
<strong>{ invalidMessage }</strong>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ const columns = [{
|
|||||||
}, {
|
}, {
|
||||||
dataField: 'quality',
|
dataField: 'quality',
|
||||||
text: 'Product Quality',
|
text: 'Product Quality',
|
||||||
editorRenderer: (editorProps, value, row, column, rowIndex, columnIndex) => (
|
editorRenderer: (editorProps, value, row, rowIndex, columnIndex) => (
|
||||||
<QualityRanger { ...editorProps } value={ value } />
|
<QualityRanger { ...editorProps } value={ value } />
|
||||||
)
|
)
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
/* 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>
|
|
||||||
);
|
|
||||||
@@ -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, withOnSale } from 'utils/common';
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
const products = withOnSale(productsGenerator());
|
const products = productsGenerator();
|
||||||
|
|
||||||
function priceFormatter(cell, row) {
|
function priceFormatter(cell, row) {
|
||||||
if (row.onSale) {
|
if (row.onSale) {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
/* 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';
|
||||||
@@ -34,7 +33,7 @@ const expandRow = {
|
|||||||
}
|
}
|
||||||
return <b>+</b>;
|
return <b>+</b>;
|
||||||
},
|
},
|
||||||
expandColumnRenderer: ({ expanded, rowKey, expandable }) => {
|
expandColumnRenderer: ({ expanded }) => {
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
return (
|
return (
|
||||||
<b>-</b>
|
<b>-</b>
|
||||||
|
|||||||
@@ -51,8 +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,
|
showExpandColumn: true
|
||||||
expandByColumnOnly: true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
<BootstrapTable
|
<BootstrapTable
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ 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]
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,7 +50,6 @@ 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]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
/* 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,12 +1,10 @@
|
|||||||
/* eslint no-unused-vars: 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';
|
||||||
import Code from 'components/common/code-block';
|
import Code from 'components/common/code-block';
|
||||||
import { productsGenerator } from 'utils/common';
|
import { productsGenerator } from 'utils/common';
|
||||||
|
|
||||||
const products = productsGenerator();
|
const products = productsGenerator(87);
|
||||||
|
|
||||||
const columns = [{
|
const columns = [{
|
||||||
dataField: 'id',
|
dataField: 'id',
|
||||||
@@ -19,14 +17,16 @@ const columns = [{
|
|||||||
text: 'Product Price'
|
text: 'Product Price'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
const rowEvents = {
|
const style = `\
|
||||||
onClick: (e, row, rowIndex) => {
|
// Customizing your own sticky table style by simply overwriting .table-sticky
|
||||||
console.log(`clicked on row with index: ${rowIndex}`);
|
.react-bootstrap-table {
|
||||||
},
|
.sticky.table-sticky {
|
||||||
onMouseEnter: (e, row, rowIndex) => {
|
tbody {
|
||||||
console.log(`enter on row with index: ${rowIndex}`);
|
max-height: 200px;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const sourceCode = `\
|
const sourceCode = `\
|
||||||
import BootstrapTable from 'react-bootstrap-table-next';
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
@@ -42,16 +42,14 @@ const columns = [{
|
|||||||
text: 'Product Price'
|
text: 'Product Price'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
const hiddenRowKeys = [1, 3];
|
<BootstrapTable sticky classes="sticky" keyField="id" data={ products } columns={ columns } />
|
||||||
|
|
||||||
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const hiddenRowKeys = [1, 3];
|
|
||||||
|
|
||||||
export default () => (
|
export default () => (
|
||||||
<div>
|
<div>
|
||||||
<BootstrapTable keyField="id" data={ products } columns={ columns } hiddenRows={ hiddenRowKeys } />
|
<BootstrapTable sticky classes="sticky" keyField="id" data={ products } columns={ columns } />
|
||||||
|
|
||||||
|
<Code>{ style }</Code>
|
||||||
<Code>{ sourceCode }</Code>
|
<Code>{ sourceCode }</Code>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
43
packages/react-bootstrap-table2-example/examples/sticky-header/default.js
vendored
Normal file
43
packages/react-bootstrap-table2-example/examples/sticky-header/default.js
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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(87);
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
const sourceCode = `\
|
||||||
|
import BootstrapTable from 'react-bootstrap-table-next';
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
dataField: 'id',
|
||||||
|
text: 'Product ID'
|
||||||
|
}, {
|
||||||
|
dataField: 'name',
|
||||||
|
text: 'Product Name'
|
||||||
|
}, {
|
||||||
|
dataField: 'price',
|
||||||
|
text: 'Product Price'
|
||||||
|
}];
|
||||||
|
|
||||||
|
<BootstrapTable sticky keyField="id" data={ products } columns={ columns } />
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<div>
|
||||||
|
<BootstrapTable sticky keyField="id" data={ products } columns={ columns } />
|
||||||
|
|
||||||
|
<Code>{ sourceCode }</Code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table2-example",
|
"name": "react-bootstrap-table2-example",
|
||||||
"version": "1.0.12",
|
"version": "1.0.8",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
/* eslint no-mixed-operators: 0 */
|
/* eslint no-mixed-operators: 0 */
|
||||||
/* eslint no-param-reassign: 0 */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* products generator for stories
|
* products generator for stories
|
||||||
@@ -23,12 +22,6 @@ 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,7 +55,6 @@ 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';
|
||||||
@@ -79,7 +78,6 @@ 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';
|
||||||
@@ -120,7 +118,6 @@ 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';
|
||||||
@@ -171,6 +168,10 @@ import CustomCSV from 'examples/csv/custom-csv';
|
|||||||
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
|
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
|
||||||
import TableOverlay from 'examples/loading-overlay/table-overlay';
|
import TableOverlay from 'examples/loading-overlay/table-overlay';
|
||||||
|
|
||||||
|
// sticky header table
|
||||||
|
import StickyHeaderTable from 'examples/sticky-header/default';
|
||||||
|
import StickyHeaderCustomStyleTable from 'examples/sticky-header/customized-style.js';
|
||||||
|
|
||||||
// remote
|
// remote
|
||||||
import RemoteSort from 'examples/remote/remote-sort';
|
import RemoteSort from 'examples/remote/remote-sort';
|
||||||
import RemoteFilter from 'examples/remote/remote-filter';
|
import RemoteFilter from 'examples/remote/remote-filter';
|
||||||
@@ -265,14 +266,12 @@ 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)
|
||||||
@@ -317,7 +316,6 @@ 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 />)
|
||||||
@@ -368,6 +366,11 @@ storiesOf('Export CSV', module)
|
|||||||
.add('Export Custom Data', () => <ExportCustomData />)
|
.add('Export Custom Data', () => <ExportCustomData />)
|
||||||
.add('Custom CSV', () => <CustomCSV />);
|
.add('Custom CSV', () => <CustomCSV />);
|
||||||
|
|
||||||
|
storiesOf('Sticky header', module)
|
||||||
|
.addDecorator(bootstrapStyle())
|
||||||
|
.add('Default sticky header', () => <StickyHeaderTable />)
|
||||||
|
.add('Custom style for sticky header', () => <StickyHeaderCustomStyleTable />);
|
||||||
|
|
||||||
storiesOf('EmptyTableOverlay', module)
|
storiesOf('EmptyTableOverlay', module)
|
||||||
.addDecorator(bootstrapStyle())
|
.addDecorator(bootstrapStyle())
|
||||||
.add('Empty Table Overlay', () => <EmptyTableOverlay />)
|
.add('Empty Table Overlay', () => <EmptyTableOverlay />)
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.react-bootstrap-table {
|
||||||
|
.sticky.table-sticky {
|
||||||
|
tbody {
|
||||||
|
max-height: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,3 +12,4 @@
|
|||||||
@import "sort/index";
|
@import "sort/index";
|
||||||
@import "search/index";
|
@import "search/index";
|
||||||
@import "loading-overlay/index";
|
@import "loading-overlay/index";
|
||||||
|
@import "sticky/index";
|
||||||
|
|||||||
@@ -115,27 +115,6 @@ 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.1.0",
|
"version": "1.0.1",
|
||||||
"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,17 +7,6 @@ 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]]) {
|
||||||
@@ -27,21 +16,11 @@ 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 = getOptionValue(props.options, props.defaultValue) !== undefined;
|
const isSelected = props.options[props.defaultValue] !== undefined;
|
||||||
this.state = { isSelected };
|
this.state = { isSelected };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,14 +66,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +128,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.oneOfType([PropTypes.object, PropTypes.array]).isRequired,
|
options: PropTypes.object.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.4",
|
"version": "1.0.3",
|
||||||
"description": "it's the pagination addon for react-bootstrap-table2",
|
"description": "it's the pagination addon for react-bootstrap-table2",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -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 } of { props.dataSize }
|
Showing rows { props.from } to { props.to + 1 } of { props.dataSize }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import statelessDrcorator from './statelessOp';
|
import statelessDecorator from './statelessOp';
|
||||||
|
|
||||||
import createContext from './src/search/context';
|
import createContext from './src/search/context';
|
||||||
|
|
||||||
const ToolkitContext = React.createContext();
|
const ToolkitContext = React.createContext();
|
||||||
|
|
||||||
class ToolkitProvider extends statelessDrcorator(React.Component) {
|
class ToolkitProvider extends statelessDecorator(React.Component) {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
keyField: PropTypes.string.isRequired,
|
keyField: PropTypes.string.isRequired,
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ToolkitContext from './context';
|
import ToolkitContext from './context';
|
||||||
|
|
||||||
const Toolkitprovider = props => (
|
const ToolkitProvider = props => (
|
||||||
<ToolkitContext.Provider { ...props }>
|
<ToolkitContext.Provider { ...props }>
|
||||||
<ToolkitContext.Consumer>
|
<ToolkitContext.Consumer>
|
||||||
{
|
{
|
||||||
tookKitProps => props.children(tookKitProps)
|
toolkitProps => props.children(toolkitProps)
|
||||||
}
|
}
|
||||||
</ToolkitContext.Consumer>
|
</ToolkitContext.Consumer>
|
||||||
</ToolkitContext.Provider>
|
</ToolkitContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
Toolkitprovider.propTypes = {
|
ToolkitProvider.propTypes = {
|
||||||
children: PropTypes.func.isRequired
|
children: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Toolkitprovider;
|
export default ToolkitProvider;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-bootstrap-table-next",
|
"name": "react-bootstrap-table-next",
|
||||||
"version": "1.4.3",
|
"version": "1.3.1",
|
||||||
"description": "Next generation of react-bootstrap-table",
|
"description": "Next generation of react-bootstrap-table",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
|
|
||||||
// Exposed APIs
|
// Exposed APIs
|
||||||
getData() {
|
getData() {
|
||||||
return this.visibleRows();
|
return this.props.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
@@ -57,7 +57,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
rowEvents,
|
rowEvents,
|
||||||
selectRow,
|
selectRow,
|
||||||
expandRow,
|
expandRow,
|
||||||
cellEdit
|
cellEdit,
|
||||||
|
sticky
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses);
|
const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses);
|
||||||
@@ -66,7 +67,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
'table-striped': striped,
|
'table-striped': striped,
|
||||||
'table-hover': hover,
|
'table-hover': hover,
|
||||||
'table-bordered': bordered,
|
'table-bordered': bordered,
|
||||||
[(bootstrap4 ? 'table-sm' : 'table-condensed')]: condensed
|
'table-condensed': condensed,
|
||||||
|
'table-sticky': sticky
|
||||||
}, classes);
|
}, classes);
|
||||||
|
|
||||||
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
||||||
@@ -87,7 +89,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
|||||||
expandRow={ expandRow }
|
expandRow={ expandRow }
|
||||||
/>
|
/>
|
||||||
<Body
|
<Body
|
||||||
data={ this.getData() }
|
data={ data }
|
||||||
keyField={ keyField }
|
keyField={ keyField }
|
||||||
tabIndexCell={ tabIndexCell }
|
tabIndexCell={ tabIndexCell }
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
@@ -118,6 +120,7 @@ BootstrapTable.propTypes = {
|
|||||||
noDataIndication: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
noDataIndication: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
striped: PropTypes.bool,
|
striped: PropTypes.bool,
|
||||||
bordered: PropTypes.bool,
|
bordered: PropTypes.bool,
|
||||||
|
sticky: PropTypes.bool,
|
||||||
hover: PropTypes.bool,
|
hover: PropTypes.bool,
|
||||||
tabIndexCell: PropTypes.bool,
|
tabIndexCell: PropTypes.bool,
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
@@ -190,6 +193,7 @@ BootstrapTable.defaultProps = {
|
|||||||
remote: false,
|
remote: false,
|
||||||
striped: false,
|
striped: false,
|
||||||
bordered: true,
|
bordered: true,
|
||||||
|
sticky: false,
|
||||||
hover: false,
|
hover: false,
|
||||||
condensed: false,
|
condensed: false,
|
||||||
noDataIndication: null,
|
noDataIndication: null,
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ 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];
|
||||||
@@ -76,7 +73,6 @@ 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,
|
||||||
|
|||||||
@@ -43,14 +43,6 @@ 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
|
||||||
@@ -58,9 +50,13 @@ 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) => {
|
||||||
@@ -82,9 +78,8 @@ 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) {
|
||||||
result = onSelectAll(
|
onSelectAll(
|
||||||
!isUnSelect,
|
!isUnSelect,
|
||||||
dataOperator.getSelectedRows(
|
dataOperator.getSelectedRows(
|
||||||
data,
|
data,
|
||||||
@@ -93,10 +88,8 @@ class SelectionProvider extends React.Component {
|
|||||||
),
|
),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
if (Array.isArray(result)) {
|
|
||||||
currSelected = result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(() => ({ selected: currSelected }));
|
this.setState(() => ({ selected: currSelected }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ const Header = (props) => {
|
|||||||
sortOrder,
|
sortOrder,
|
||||||
selectRow,
|
selectRow,
|
||||||
onExternalFilter,
|
onExternalFilter,
|
||||||
expandRow
|
expandRow,
|
||||||
|
bootstrap4
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
let SelectionHeaderCellComp = () => null;
|
let SelectionHeaderCellComp = () => null;
|
||||||
@@ -49,6 +50,7 @@ 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 }
|
||||||
@@ -76,7 +78,8 @@ 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;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import _ from '../utils';
|
|
||||||
import ColumnResolver from './column-resolver';
|
import ColumnResolver from './column-resolver';
|
||||||
|
|
||||||
export default ExtendBase =>
|
export default ExtendBase =>
|
||||||
@@ -16,13 +15,4 @@ 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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ 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,
|
||||||
@@ -34,12 +33,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, expandable, expandColumnRenderer, tabIndex, rowKey } = this.props;
|
const { expanded, expandColumnRenderer, tabIndex } = this.props;
|
||||||
const attrs = {};
|
const attrs = {};
|
||||||
if (tabIndex !== -1) attrs.tabIndex = tabIndex;
|
if (tabIndex !== -1) attrs.tabIndex = tabIndex;
|
||||||
|
|
||||||
@@ -47,10 +46,8 @@ export default class ExpandCell extends Component {
|
|||||||
<td onClick={ this.handleClick } { ...attrs }>
|
<td onClick={ this.handleClick } { ...attrs }>
|
||||||
{
|
{
|
||||||
expandColumnRenderer ? expandColumnRenderer({
|
expandColumnRenderer ? expandColumnRenderer({
|
||||||
expandable,
|
expanded
|
||||||
expanded,
|
}) : (expanded ? '(-)' : '(+)')
|
||||||
rowKey
|
|
||||||
}) : (expandable ? (expanded ? '(-)' : '(+)') : '')
|
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export default class SelectionCell extends Component {
|
|||||||
<BootstrapContext.Consumer>
|
<BootstrapContext.Consumer>
|
||||||
{
|
{
|
||||||
({ bootstrap4 }) => (
|
({ bootstrap4 }) => (
|
||||||
<td onClick={ this.handleClick } { ...attrs }>
|
<td data-row-selection onClick={ this.handleClick } { ...attrs }>
|
||||||
{
|
{
|
||||||
selectionRenderer ? selectionRenderer({
|
selectionRenderer ? selectionRenderer({
|
||||||
mode: inputType,
|
mode: inputType,
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ 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)
|
||||||
) {
|
) {
|
||||||
@@ -55,7 +54,6 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
|
|||||||
selectRow,
|
selectRow,
|
||||||
expandRow,
|
expandRow,
|
||||||
expanded,
|
expanded,
|
||||||
expandable,
|
|
||||||
selected,
|
selected,
|
||||||
selectable,
|
selectable,
|
||||||
visibleColumnSize,
|
visibleColumnSize,
|
||||||
@@ -86,7 +84,6 @@ 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
|
||||||
|
|||||||
1
packages/react-bootstrap-table2/style/partials/_all.scss
Normal file
1
packages/react-bootstrap-table2/style/partials/_all.scss
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import "./sticky";
|
||||||
56
packages/react-bootstrap-table2/style/partials/_sticky.scss
Normal file
56
packages/react-bootstrap-table2/style/partials/_sticky.scss
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
.react-bootstrap-table {
|
||||||
|
.table-sticky {
|
||||||
|
thead,
|
||||||
|
tbody {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
tr {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&[data-row-selection] {
|
||||||
|
width: 30px;
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable double strips when table was displayed in bordered.
|
||||||
|
table.table-sticky.table-bordered {
|
||||||
|
border-left: 0;
|
||||||
|
|
||||||
|
thead,
|
||||||
|
tbody {
|
||||||
|
tr {
|
||||||
|
th {
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
td {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@import "partials/all";
|
||||||
|
|
||||||
.react-bootstrap-table {
|
.react-bootstrap-table {
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@@ -55,8 +57,10 @@
|
|||||||
content: "\2193";
|
content: "\2193";
|
||||||
}
|
}
|
||||||
|
|
||||||
th[data-row-selection] {
|
th[data-row-selection],
|
||||||
|
td[data-row-selection] {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
min-width: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
th > .selection-input-4,
|
th > .selection-input-4,
|
||||||
|
|||||||
@@ -25,51 +25,6 @@ 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(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user