mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-06-29 13:40:07 +00:00
Compare commits
87 Commits
react-boot
...
react-boot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1e5c0cb20 | ||
|
|
7ee38a647f | ||
|
|
01ec19344d | ||
|
|
19be67c914 | ||
|
|
ae4d38cae6 | ||
|
|
81a6428a03 | ||
|
|
166affc4c1 | ||
|
|
d0fb46e39f | ||
|
|
828844a1e9 | ||
|
|
774293b76d | ||
|
|
e77cbdb2df | ||
|
|
ef2f828572 | ||
|
|
15731932cf | ||
|
|
dd54294382 | ||
|
|
185c184f01 | ||
|
|
d45345ed10 | ||
|
|
dda8460017 | ||
|
|
6735536fd8 | ||
|
|
95623bbb5f | ||
|
|
9567c7829d | ||
|
|
8499991c41 | ||
|
|
1e76ca9bdb | ||
|
|
fa13550d8c | ||
|
|
709d59ce62 | ||
|
|
66329ecdbf | ||
|
|
ee6cec5a2d | ||
|
|
52fc84899b | ||
|
|
8c10867b8c | ||
|
|
640ada7659 | ||
|
|
73a5c34535 | ||
|
|
2879cf891e | ||
|
|
994ed2e395 | ||
|
|
4b790e4bec | ||
|
|
21e7c3a53a | ||
|
|
6fce0d7066 | ||
|
|
154f1c91c3 | ||
|
|
02d78e5104 | ||
|
|
41cc6b01af | ||
|
|
bd410e7303 | ||
|
|
eced3eef1f | ||
|
|
ca5a41a8b3 | ||
|
|
7a31729ebb | ||
|
|
3a8faf8170 | ||
|
|
532581bb6e | ||
|
|
c228b229d2 | ||
|
|
10adbf472c | ||
|
|
a6e2f0f8f8 | ||
|
|
f1d93853ec | ||
|
|
bb7243c5db | ||
|
|
3ea816b2e6 | ||
|
|
b268c4e0cd | ||
|
|
8b8f336878 | ||
|
|
8517248aee | ||
|
|
ae0cd8a32f | ||
|
|
51c82cdfb3 | ||
|
|
8e087329b3 | ||
|
|
ee2885d055 | ||
|
|
901307e471 | ||
|
|
4ff5be706a | ||
|
|
f8a3fedbb2 | ||
|
|
0bf5831b4e | ||
|
|
dd0b8c6b0f | ||
|
|
8f028d9dd4 | ||
|
|
2c68f22646 | ||
|
|
02d566bb32 | ||
|
|
2b12045017 | ||
|
|
0cdf086d56 | ||
|
|
d4fa9a84e3 | ||
|
|
c84fc84b9e | ||
|
|
ad8cdde513 | ||
|
|
db19e7dd9b | ||
|
|
33b36e5108 | ||
|
|
7209441eb6 | ||
|
|
7a1ed67847 | ||
|
|
eaf9f4cd39 | ||
|
|
f0d85520c0 | ||
|
|
0e2862baa5 | ||
|
|
5ac058c489 | ||
|
|
ac38d2f28e | ||
|
|
591abaae6e | ||
|
|
b76566126c | ||
|
|
687583536a | ||
|
|
d136ec3197 | ||
|
|
37db43f5a7 | ||
|
|
a966900752 | ||
|
|
3b1fc3a559 | ||
|
|
849d9af8c4 |
@@ -13,7 +13,7 @@ Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-tab
|
||||
* [`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)
|
||||
|
||||
This can help your application with less bundled size and also help us have clean design to avoid handling to much logic in kernal 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
|
||||
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).
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* [hover](#hover)
|
||||
* [condensed](#condensed)
|
||||
* [id](#id)
|
||||
* [tabIndexCell](#tabIndexCell)
|
||||
* [classes](#classes)
|
||||
* [wrapperClasses](#wrapperClasses)
|
||||
* [headerClasses](#headerClasses)
|
||||
@@ -112,6 +113,10 @@ Same as bootstrap `.table-condensed` class for making a table more compact by cu
|
||||
|
||||
### <a name='id'>id - [String]</a>
|
||||
Customize id on `table` element.
|
||||
|
||||
### <a name='tabIndexCell'>tabIndexCell - [Bool]</a>
|
||||
Enable the `tabIndex` attribute on `<td>` element.
|
||||
|
||||
### <a name='classes'>classes - [String]</a>
|
||||
Customize class on `table` element.
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ $ npm install react-bootstrap-table2-editor --save
|
||||
* [blurToSave](#blurToSave)
|
||||
* [nonEditableRows](#nonEditableRows)
|
||||
* [timeToCloseMessage](#timeToCloseMessage)
|
||||
* [autoSelectText](#autoSelectText)
|
||||
* [beforeSaveCell](#beforeSaveCell)
|
||||
* [afterSaveCell](#afterSaveCell)
|
||||
* [errorMessage](#errorMessage)
|
||||
@@ -43,6 +44,11 @@ Default is `false`, enable it will be able to save the cell automatically when b
|
||||
### <a name='nonEditableRows'>cellEdit.nonEditableRows - [Function]</a>
|
||||
`cellEdit.nonEditableRows` accept a callback function and expect return an array which used to restrict all the columns of some rows as non-editable. So the each item in return array should be rowkey(`keyField`)
|
||||
|
||||
### <a name='autoSelectText'>cellEdit.autoSelectText - [Bool]</a>
|
||||
Default is false, when enable it, `react-bootstrap-table2` will help you to select the text in the text input automatically when editing.
|
||||
|
||||
> NOTE: This props only work for `text` and `textarea`.
|
||||
|
||||
### <a name='timeToCloseMessage'>cellEdit.timeToCloseMessage - [Function]</a>
|
||||
If a [`column.validator`](./columns.md#validator) defined and the new value is invalid, `react-bootstrap-table2` will popup a alert at the bottom of editor. `cellEdit.timeToCloseMessage` is a chance to let you decide how long the alert should be stay. Default is 3000 millisecond.
|
||||
|
||||
|
||||
@@ -7,11 +7,13 @@ Available properties in a column object:
|
||||
* [text (**required**)](#text)
|
||||
|
||||
#### Optional
|
||||
* [isDummyField](#isDummyField)
|
||||
* [hidden](#hidden)
|
||||
* [formatter](#formatter)
|
||||
* [formatExtraData](#formatExtraData)
|
||||
* [sort](#sort)
|
||||
* [sortFunc](#sortFunc)
|
||||
* [sortCaret](#sortCaret)
|
||||
* [onSort](#onSort)
|
||||
* [classes](#classes)
|
||||
* [style](#style)
|
||||
@@ -84,6 +86,11 @@ dataField: 'address.city'
|
||||
## <a name='text'>column.text (**required**) - [String]</a>
|
||||
`text` will be the column text in header column by default, if your header is not only text or you want to customize the header column, please check [`column.headerFormatter`](#headerFormatter)
|
||||
|
||||
## <a name='isDummyField'>column.isDummyField - [Bool]</a>
|
||||
Sometime, you just want to have a column which is not perform any data but just some action components. In this situation, we suggest you to use `isDummyField`. If column is dummy, the [`column.dataField`](#dataField) can be any string value, cause of it's meaningless.
|
||||
|
||||
There's only one different for dummy column than normal column, which is dummy column will compare the whole row value instead of cell value when call `shouldComponentUpdate`.
|
||||
|
||||
## <a name='hidden'>column.hidden - [Bool]</a>
|
||||
`hidden` allow you to hide column when `true` given.
|
||||
|
||||
@@ -148,6 +155,20 @@ Enable the column sort via a `true` value given.
|
||||
}
|
||||
```
|
||||
|
||||
## <a name='sortCaret'>column.sortCaret - [Function]</a>
|
||||
Use`column.sortCaret` to custom the sort caret. This callback function accept two arguments: `order` and `column`
|
||||
|
||||
```js
|
||||
{
|
||||
// omit...
|
||||
sort: true,
|
||||
sortCaret: (order, column) => {
|
||||
return //...
|
||||
}
|
||||
}
|
||||
```
|
||||
> The possible value of `order` argument is **`asc`**, **`desc`** and **`undefined`**.
|
||||
|
||||
## <a name='classes'>column.classes - [String | Function]</a>
|
||||
It's available to have custom class on table column:
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
* [onExpand](#onExpand)
|
||||
* [onExpandAll](#onExpandAll)
|
||||
* [showExpandColumn](#showExpandColumn)
|
||||
* [onlyOneExpanding](#onlyOneExpanding)
|
||||
* [expandByColumnOnly](#expandByColumnOnly)
|
||||
* [expandColumnRenderer](#expandColumnRenderer)
|
||||
* [expandHeaderColumnRenderer](#expandHeaderColumnRenderer)
|
||||
|
||||
@@ -127,3 +129,24 @@ const expandRow = {
|
||||
showExpandColumn: true
|
||||
};
|
||||
```
|
||||
|
||||
### <a name='onlyOneExpanding'>expandRow.onlyOneExpanding - [Bool]</a>
|
||||
Default is `false`. Enable this will only allow one row get expand at the same time.
|
||||
|
||||
```js
|
||||
const expandRow = {
|
||||
renderer: (row) => ...
|
||||
onlyOneExpanding: true
|
||||
};
|
||||
```
|
||||
|
||||
### <a name='expandByColumnOnly'>expandRow.expandByColumnOnly - [Bool]</a>
|
||||
Default is `false`. If you want to restrict user to expand/collapse row via clicking the expand column only, you can enable it.
|
||||
|
||||
```js
|
||||
const expandRow = {
|
||||
renderer: (row) => ...,
|
||||
showExpandColumn: true,
|
||||
expandByColumnOnly: true
|
||||
};
|
||||
```
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
* [bgColor](#bgColor)
|
||||
* [nonSelectable)](#nonSelectable)
|
||||
* [clickToSelect)](#clickToSelect)
|
||||
* [clickToExpand)](#clickToExpand)
|
||||
* [clickToEdit](#clickToEdit)
|
||||
* [onSelect](#onSelect)
|
||||
* [onSelectAll](#onSelectAll)
|
||||
* [hideSelectColumn](#hideSelectColumn)
|
||||
* [hideSelectAll](#hideSelectAll)
|
||||
* [selectionRenderer](#selectionRenderer)
|
||||
* [selectionHeaderRenderer](#selectionHeaderRenderer)
|
||||
|
||||
@@ -147,6 +149,16 @@ const selectRow = {
|
||||
> Note: When you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing
|
||||
> If you want to click on row to select row and edit cell simultaneously, you are suppose to enable [`selectRow.clickToEdit`](#clickToEdit)
|
||||
|
||||
### <a name='clickToExpand'>selectRow.clickToExpand - [Bool]</a>
|
||||
Default is false, enable it will let user able to expand and select row when user clicking on the row.
|
||||
|
||||
```js
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToExpand: true
|
||||
};
|
||||
```
|
||||
|
||||
### <a name='clickToEdit'>selectRow.clickToEdit - [Bool]</a>
|
||||
Able to click to edit cell and select row
|
||||
|
||||
@@ -222,3 +234,13 @@ const selectRow = {
|
||||
bgColor: 'red'
|
||||
};
|
||||
```
|
||||
|
||||
### <a name='hideSelectAll'>selectRow.hideSelectAll - [Bool]</a>
|
||||
Default is `false`, if you don't want to render the select all checkbox on the header of selection column, give this prop as `true`!
|
||||
|
||||
```js
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
hideSelectAll: true
|
||||
};
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
import Adapter from 'enzyme-adapter-react-16.3';
|
||||
import { configure } from 'enzyme';
|
||||
|
||||
const configureEnzyme = () => {
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
"babel-preset-stage-0": "6.24.1",
|
||||
"babel-register": "6.24.1",
|
||||
"css-loader": "0.28.1",
|
||||
"enzyme": "3.3.0",
|
||||
"enzyme-adapter-react-16": "1.1.1",
|
||||
"enzyme": "3.4.0",
|
||||
"enzyme-adapter-react-16.3": "1.0.0",
|
||||
"enzyme-to-json": "3.3.4",
|
||||
"eslint": "4.5.0",
|
||||
"eslint-config-airbnb": "15.1.0",
|
||||
@@ -82,8 +82,8 @@
|
||||
"dependencies": {
|
||||
"classnames": "2.2.5",
|
||||
"prop-types": "15.5.10",
|
||||
"react": "16.3.2",
|
||||
"react-dom": "16.3.2",
|
||||
"react": "16.4.0",
|
||||
"react-dom": "16.4.0",
|
||||
"underscore": "1.9.1"
|
||||
},
|
||||
"jest": {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import createContext from './src/context';
|
||||
import editingCellFactory from './src/editing-cell';
|
||||
import withRowLevelCellEdit from './src/row-consumer';
|
||||
import createEditingCell from './src/editing-cell-consumer';
|
||||
import {
|
||||
EDITTYPE,
|
||||
CLICK_TO_CELL_EDIT,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK
|
||||
} from './src/const';
|
||||
|
||||
export default (options = {}) => ({
|
||||
createContext,
|
||||
editingCellFactory,
|
||||
CLICK_TO_CELL_EDIT,
|
||||
createEditingCell,
|
||||
withRowLevelCellEdit,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK,
|
||||
options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-editor",
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.0",
|
||||
"description": "it's the editor addon for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -13,7 +13,9 @@ class CheckBoxEditor extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { didMount } = this.props;
|
||||
this.checkbox.focus();
|
||||
if (didMount) didMount();
|
||||
}
|
||||
|
||||
getValue() {
|
||||
@@ -28,7 +30,7 @@ class CheckBoxEditor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { defaultValue, className, ...rest } = this.props;
|
||||
const { defaultValue, didMount, className, ...rest } = this.props;
|
||||
const editorClass = cs('editor edit-chseckbox checkbox', className);
|
||||
return (
|
||||
<input
|
||||
@@ -50,12 +52,14 @@ CheckBoxEditor.propTypes = {
|
||||
]),
|
||||
value: PropTypes.string,
|
||||
defaultValue: PropTypes.any,
|
||||
onChange: PropTypes.func
|
||||
onChange: PropTypes.func,
|
||||
didMount: PropTypes.func
|
||||
};
|
||||
CheckBoxEditor.defaultProps = {
|
||||
className: '',
|
||||
value: 'on:off',
|
||||
defaultValue: false,
|
||||
onChange: undefined
|
||||
onChange: undefined,
|
||||
didMount: undefined
|
||||
};
|
||||
export default CheckBoxEditor;
|
||||
|
||||
@@ -4,15 +4,14 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const';
|
||||
|
||||
const CellEditContext = React.createContext();
|
||||
|
||||
export default (
|
||||
_,
|
||||
dataOperator,
|
||||
isRemoteCellEdit,
|
||||
handleCellChange
|
||||
) => {
|
||||
let EditingCell;
|
||||
const CellEditContext = React.createContext();
|
||||
|
||||
class CellEditProvider extends React.Component {
|
||||
static propTypes = {
|
||||
data: PropTypes.array.isRequired,
|
||||
@@ -23,6 +22,7 @@ export default (
|
||||
blurToSave: PropTypes.bool,
|
||||
beforeSaveCell: PropTypes.func,
|
||||
afterSaveCell: PropTypes.func,
|
||||
onStartEdit: PropTypes.func,
|
||||
nonEditableRows: PropTypes.func,
|
||||
timeToCloseMessage: PropTypes.number,
|
||||
errorMessage: PropTypes.any
|
||||
@@ -31,7 +31,6 @@ export default (
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
EditingCell = props.cellEdit.editingCellFactory(_);
|
||||
this.startEditing = this.startEditing.bind(this);
|
||||
this.escapeEditing = this.escapeEditing.bind(this);
|
||||
this.completeEditing = this.completeEditing.bind(this);
|
||||
@@ -101,8 +100,6 @@ export default (
|
||||
const {
|
||||
cellEdit: {
|
||||
options: { nonEditableRows, errorMessage, ...optionsRest },
|
||||
editingCellFactory,
|
||||
createContext,
|
||||
...cellEditRest
|
||||
}
|
||||
} = this.props;
|
||||
@@ -111,7 +108,6 @@ export default (
|
||||
...optionsRest,
|
||||
...cellEditRest,
|
||||
...this.state,
|
||||
EditingCell,
|
||||
nonEditableRows: _.isDefined(nonEditableRows) ? nonEditableRows() : [],
|
||||
onStart: this.startEditing,
|
||||
onEscape: this.escapeEditing,
|
||||
@@ -120,7 +116,7 @@ export default (
|
||||
|
||||
return (
|
||||
<CellEditContext.Provider
|
||||
value={ { cellEdit: newCellEdit } }
|
||||
value={ { ...newCellEdit } }
|
||||
>
|
||||
{ this.props.children }
|
||||
</CellEditContext.Provider>
|
||||
@@ -128,7 +124,8 @@ export default (
|
||||
}
|
||||
}
|
||||
return {
|
||||
Provider: CellEditProvider,
|
||||
Consumer: CellEditContext.Consumer
|
||||
Provider: CellEditProvider
|
||||
};
|
||||
};
|
||||
|
||||
export const Consumer = CellEditContext.Consumer;
|
||||
|
||||
@@ -5,9 +5,10 @@ import PropTypes from 'prop-types';
|
||||
|
||||
class DateEditor extends Component {
|
||||
componentDidMount() {
|
||||
const { defaultValue } = this.props;
|
||||
const { defaultValue, didMount } = this.props;
|
||||
this.date.valueAsDate = new Date(defaultValue);
|
||||
this.date.focus();
|
||||
if (didMount) didMount();
|
||||
}
|
||||
|
||||
getValue() {
|
||||
@@ -15,7 +16,7 @@ class DateEditor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { defaultValue, className, ...rest } = this.props;
|
||||
const { defaultValue, didMount, className, ...rest } = this.props;
|
||||
const editorClass = cs('form-control editor edit-date', className);
|
||||
return (
|
||||
<input
|
||||
@@ -33,10 +34,12 @@ DateEditor.propTypes = {
|
||||
PropTypes.string,
|
||||
PropTypes.object
|
||||
]),
|
||||
defaultValue: PropTypes.string
|
||||
defaultValue: PropTypes.string,
|
||||
didMount: PropTypes.func
|
||||
};
|
||||
DateEditor.defaultProps = {
|
||||
className: '',
|
||||
defaultValue: ''
|
||||
defaultValue: '',
|
||||
didMount: undefined
|
||||
};
|
||||
export default DateEditor;
|
||||
|
||||
@@ -5,9 +5,10 @@ import PropTypes from 'prop-types';
|
||||
|
||||
class DropDownEditor extends Component {
|
||||
componentDidMount() {
|
||||
const { defaultValue } = this.props;
|
||||
const { defaultValue, didMount } = this.props;
|
||||
this.select.value = defaultValue;
|
||||
this.select.focus();
|
||||
if (didMount) didMount();
|
||||
}
|
||||
|
||||
getValue() {
|
||||
@@ -15,7 +16,7 @@ class DropDownEditor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { defaultValue, className, options, ...rest } = this.props;
|
||||
const { defaultValue, didMount, className, options, ...rest } = this.props;
|
||||
const editorClass = cs('form-control editor edit-select', className);
|
||||
|
||||
const attr = {
|
||||
@@ -51,11 +52,13 @@ DropDownEditor.propTypes = {
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.any
|
||||
}))
|
||||
]).isRequired
|
||||
]).isRequired,
|
||||
didMount: PropTypes.func
|
||||
};
|
||||
DropDownEditor.defaultProps = {
|
||||
className: '',
|
||||
defaultValue: '',
|
||||
style: {}
|
||||
style: {},
|
||||
didMount: undefined
|
||||
};
|
||||
export default DropDownEditor;
|
||||
|
||||
44
packages/react-bootstrap-table2-editor/src/editing-cell-consumer.js
vendored
Normal file
44
packages/react-bootstrap-table2-editor/src/editing-cell-consumer.js
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import { Consumer } from './context';
|
||||
import createEditingCell from './editing-cell';
|
||||
|
||||
export default (_, onStartEdit) => {
|
||||
const EditingCell = createEditingCell(_, onStartEdit);
|
||||
const renderWithEditingCell = (props, cellEdit) => {
|
||||
const content = _.get(props.row, props.column.dataField);
|
||||
let editCellstyle = props.column.editCellStyle || {};
|
||||
let editCellclasses = props.column.editCellClasses;
|
||||
if (_.isFunction(props.column.editCellStyle)) {
|
||||
editCellstyle = props.column.editCellStyle(
|
||||
content,
|
||||
props.row,
|
||||
props.rowIndex,
|
||||
props.columnIndex
|
||||
);
|
||||
}
|
||||
if (_.isFunction(props.column.editCellClasses)) {
|
||||
editCellclasses = props.column.editCellClasses(
|
||||
content,
|
||||
props.row,
|
||||
props.rowIndex,
|
||||
props.columnIndex)
|
||||
;
|
||||
}
|
||||
|
||||
return (
|
||||
<EditingCell
|
||||
{ ...props }
|
||||
className={ editCellclasses }
|
||||
style={ editCellstyle }
|
||||
{ ...cellEdit }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return props => (
|
||||
<Consumer>
|
||||
{ cellEdit => renderWithEditingCell(props, cellEdit) }
|
||||
</Consumer>
|
||||
);
|
||||
};
|
||||
@@ -14,7 +14,7 @@ import TextEditor from './text-editor';
|
||||
import EditorIndicator from './editor-indicator';
|
||||
import { TIME_TO_CLOSE_MESSAGE, EDITTYPE } from './const';
|
||||
|
||||
export default _ =>
|
||||
export default (_, onStartEdit) =>
|
||||
class EditingCell extends Component {
|
||||
static propTypes = {
|
||||
row: PropTypes.object.isRequired,
|
||||
@@ -24,6 +24,7 @@ export default _ =>
|
||||
onUpdate: PropTypes.func.isRequired,
|
||||
onEscape: PropTypes.func.isRequired,
|
||||
timeToCloseMessage: PropTypes.number,
|
||||
autoSelectText: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object
|
||||
}
|
||||
@@ -31,6 +32,7 @@ export default _ =>
|
||||
static defaultProps = {
|
||||
timeToCloseMessage: TIME_TO_CLOSE_MESSAGE,
|
||||
className: null,
|
||||
autoSelectText: false,
|
||||
style: {}
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ export default _ =>
|
||||
|
||||
render() {
|
||||
let editor;
|
||||
const { row, column, className, style, rowIndex, columnIndex } = this.props;
|
||||
const { row, column, className, style, rowIndex, columnIndex, autoSelectText } = this.props;
|
||||
const { dataField } = column;
|
||||
|
||||
const value = _.get(row, dataField);
|
||||
@@ -151,6 +153,10 @@ export default _ =>
|
||||
onBlur: this.handleBlur
|
||||
};
|
||||
|
||||
if (onStartEdit) {
|
||||
editorProps.didMount = () => onStartEdit(row, column, rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
const isDefaultEditorDefined = _.isObject(column.editor);
|
||||
|
||||
if (isDefaultEditorDefined) {
|
||||
@@ -170,13 +176,13 @@ export default _ =>
|
||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.SELECT) {
|
||||
editor = <DropdownEditor { ...editorProps } />;
|
||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.TEXTAREA) {
|
||||
editor = <TextAreaEditor { ...editorProps } />;
|
||||
editor = <TextAreaEditor { ...editorProps } autoSelectText={ autoSelectText } />;
|
||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.CHECKBOX) {
|
||||
editor = <CheckBoxEditor { ...editorProps } />;
|
||||
} else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.DATE) {
|
||||
editor = <DateEditor { ...editorProps } />;
|
||||
} else {
|
||||
editor = <TextEditor { ...editorProps } />;
|
||||
editor = <TextEditor { ...editorProps } autoSelectText={ autoSelectText } />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
43
packages/react-bootstrap-table2-editor/src/row-consumer.js
vendored
Normal file
43
packages/react-bootstrap-table2-editor/src/row-consumer.js
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import { DELAY_FOR_DBCLICK, DBCLICK_TO_CELL_EDIT, CLICK_TO_CELL_EDIT } from './const';
|
||||
import { Consumer } from './context';
|
||||
|
||||
export default (Component, selectRowEnabled) => {
|
||||
const renderWithCellEdit = (props, cellEdit) => {
|
||||
const key = props.value;
|
||||
const editableRow = !(
|
||||
cellEdit.nonEditableRows.length > 0 &&
|
||||
cellEdit.nonEditableRows.indexOf(key) > -1
|
||||
);
|
||||
|
||||
const attrs = {};
|
||||
|
||||
if (selectRowEnabled && cellEdit.mode === DBCLICK_TO_CELL_EDIT) {
|
||||
attrs.DELAY_FOR_DBCLICK = DELAY_FOR_DBCLICK;
|
||||
}
|
||||
|
||||
return (
|
||||
<Component
|
||||
{ ...props }
|
||||
{ ...attrs }
|
||||
editingRowIdx={ cellEdit.ridx }
|
||||
editingColIdx={ cellEdit.cidx }
|
||||
editable={ editableRow }
|
||||
onStart={ cellEdit.onStart }
|
||||
clickToEdit={ cellEdit.mode === CLICK_TO_CELL_EDIT }
|
||||
dbclickToEdit={ cellEdit.mode === DBCLICK_TO_CELL_EDIT }
|
||||
/>
|
||||
);
|
||||
};
|
||||
function withConsumer(props) {
|
||||
return (
|
||||
<Consumer>
|
||||
{ cellEdit => renderWithCellEdit(props, cellEdit) }
|
||||
</Consumer>
|
||||
);
|
||||
}
|
||||
|
||||
withConsumer.displayName = 'WithCellEditingRowConsumer';
|
||||
return withConsumer;
|
||||
};
|
||||
@@ -5,9 +5,11 @@ import PropTypes from 'prop-types';
|
||||
|
||||
class TextEditor extends Component {
|
||||
componentDidMount() {
|
||||
const { defaultValue } = this.props;
|
||||
const { defaultValue, didMount, autoSelectText } = this.props;
|
||||
this.text.value = defaultValue;
|
||||
this.text.focus();
|
||||
if (autoSelectText) this.text.select();
|
||||
if (didMount) didMount();
|
||||
}
|
||||
|
||||
getValue() {
|
||||
@@ -15,7 +17,7 @@ class TextEditor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { defaultValue, className, ...rest } = this.props;
|
||||
const { defaultValue, didMount, className, autoSelectText, ...rest } = this.props;
|
||||
const editorClass = cs('form-control editor edit-text', className);
|
||||
return (
|
||||
<input
|
||||
@@ -36,10 +38,14 @@ TextEditor.propTypes = {
|
||||
defaultValue: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.number
|
||||
])
|
||||
]),
|
||||
autoSelectText: PropTypes.bool,
|
||||
didMount: PropTypes.func
|
||||
};
|
||||
TextEditor.defaultProps = {
|
||||
className: null,
|
||||
defaultValue: ''
|
||||
defaultValue: '',
|
||||
autoSelectText: false,
|
||||
didMount: undefined
|
||||
};
|
||||
export default TextEditor;
|
||||
|
||||
@@ -10,9 +10,11 @@ class TextAreaEditor extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { defaultValue } = this.props;
|
||||
const { defaultValue, didMount, autoSelectText } = this.props;
|
||||
this.text.value = defaultValue;
|
||||
this.text.focus();
|
||||
if (autoSelectText) this.text.select();
|
||||
if (didMount) didMount();
|
||||
}
|
||||
|
||||
getValue() {
|
||||
@@ -27,7 +29,7 @@ class TextAreaEditor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { defaultValue, className, ...rest } = this.props;
|
||||
const { defaultValue, didMount, className, autoSelectText, ...rest } = this.props;
|
||||
const editorClass = cs('form-control editor edit-textarea', className);
|
||||
return (
|
||||
<textarea
|
||||
@@ -50,11 +52,15 @@ TextAreaEditor.propTypes = {
|
||||
PropTypes.string,
|
||||
PropTypes.number
|
||||
]),
|
||||
onKeyDown: PropTypes.func
|
||||
onKeyDown: PropTypes.func,
|
||||
autoSelectText: PropTypes.bool,
|
||||
didMount: PropTypes.func
|
||||
};
|
||||
TextAreaEditor.defaultProps = {
|
||||
className: '',
|
||||
defaultValue: '',
|
||||
onKeyDown: undefined
|
||||
autoSelectText: false,
|
||||
onKeyDown: undefined,
|
||||
didMount: undefined
|
||||
};
|
||||
export default TextAreaEditor;
|
||||
|
||||
@@ -3,14 +3,13 @@ import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import _ from 'react-bootstrap-table-next/src/utils';
|
||||
import dataOperator from 'react-bootstrap-table-next/src/store/operators';
|
||||
import BootstrapTable from 'react-bootstrap-table-next/src/bootstrap-table';
|
||||
|
||||
import {
|
||||
CLICK_TO_CELL_EDIT,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK
|
||||
} from '../src/const';
|
||||
import createCellEditContext from '../src/context';
|
||||
import createCellEditContext, { Consumer } from '../src/context';
|
||||
import cellEditFactory from '../index';
|
||||
|
||||
describe('CellEditContext', () => {
|
||||
@@ -42,14 +41,7 @@ describe('CellEditContext', () => {
|
||||
|
||||
const defaultSelectRow = undefined;
|
||||
|
||||
const mockBase = jest.fn((props => (
|
||||
<BootstrapTable
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
{ ...props }
|
||||
/>
|
||||
)));
|
||||
const mockBase = jest.fn((() => null));
|
||||
|
||||
const handleCellChange = jest.fn();
|
||||
|
||||
@@ -75,11 +67,11 @@ describe('CellEditContext', () => {
|
||||
selectRow={ selectRow }
|
||||
data={ data }
|
||||
>
|
||||
<CellEditContext.Consumer>
|
||||
<Consumer>
|
||||
{
|
||||
cellEditProps => mockBase(cellEditProps)
|
||||
}
|
||||
</CellEditContext.Consumer>
|
||||
</Consumer>
|
||||
</CellEditContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -94,10 +86,6 @@ describe('CellEditContext', () => {
|
||||
expect(CellEditContext.Provider).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have correct Consumer property after calling createCellEditContext', () => {
|
||||
expect(CellEditContext.Consumer).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have correct state.ridx', () => {
|
||||
expect(wrapper.state().ridx).toBeNull();
|
||||
});
|
||||
@@ -113,14 +101,11 @@ describe('CellEditContext', () => {
|
||||
it('should pass correct cell editing props to children element', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(JSON.stringify(mockBase.mock.calls[0])).toEqual(JSON.stringify([{
|
||||
cellEdit: {
|
||||
...defaultCellEdit,
|
||||
CLICK_TO_CELL_EDIT,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK,
|
||||
...wrapper.state(),
|
||||
nonEditableRows: []
|
||||
}
|
||||
...defaultCellEdit,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK,
|
||||
...wrapper.state(),
|
||||
nonEditableRows: []
|
||||
}]));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import { mount, shallow } from 'enzyme';
|
||||
import _ from 'react-bootstrap-table-next/src/utils';
|
||||
|
||||
import cellEditFactory from '..';
|
||||
import { CLICK_TO_CELL_EDIT } from '../src/const';
|
||||
import createCellEditContext from '../src/context';
|
||||
import bindEditingCell from '../src/editing-cell-consumer';
|
||||
|
||||
describe('Editing Cell Consumer', () => {
|
||||
let wrapper;
|
||||
let cellEdit;
|
||||
const data = [{
|
||||
id: 1,
|
||||
name: 'A'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'B'
|
||||
}];
|
||||
let columns;
|
||||
const rowIndex = 1;
|
||||
const row = { id: 1, name: 'A' };
|
||||
const keyField = 'id';
|
||||
const columnIndex = 1;
|
||||
|
||||
const { Provider } = createCellEditContext(_);
|
||||
const WithCellEditComponent = bindEditingCell(_);
|
||||
|
||||
beforeEach(() => {
|
||||
columns = [{
|
||||
dataField: 'id',
|
||||
text: 'ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Name'
|
||||
}];
|
||||
});
|
||||
|
||||
describe('if column.editCellClasses is defined as string', () => {
|
||||
beforeEach(() => {
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||
columns[1].editCellClasses = 'test-class-1';
|
||||
wrapper = shallow(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent
|
||||
row={ row }
|
||||
column={ columns[1] }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
wrapper = wrapper.render();
|
||||
});
|
||||
|
||||
it('should inject className target component correctly', () => {
|
||||
expect(wrapper.hasClass(`${columns[1].editCellClasses}`)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if column.editCellStyle is defined as object', () => {
|
||||
beforeEach(() => {
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||
columns[1].editCellStyle = { color: 'pink' };
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent
|
||||
row={ row }
|
||||
column={ columns[1] }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style target component correctly', () => {
|
||||
expect(wrapper.find('.react-bootstrap-table-editing-cell').prop('style')).toEqual(columns[1].editCellStyle);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if column.editCellClasses is defined as function', () => {
|
||||
const className = 'test-class-1';
|
||||
|
||||
beforeEach(() => {
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||
columns[1].editCellClasses = jest.fn().mockReturnValue(className);
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent
|
||||
row={ row }
|
||||
column={ columns[1] }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject empty className and style to target component', () => {
|
||||
expect(wrapper.find(className)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call column.editCellClasses function correctly', () => {
|
||||
expect(columns[1].editCellClasses).toHaveBeenCalledTimes(1);
|
||||
expect(columns[1].editCellClasses).toHaveBeenCalledWith(
|
||||
_.get(row, columns[1].dataField),
|
||||
row,
|
||||
rowIndex,
|
||||
columnIndex
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if column.editCellStyle is defined as function', () => {
|
||||
const style = { color: 'blue' };
|
||||
beforeEach(() => {
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||
columns[1].editCellStyle = jest.fn().mockReturnValue(style);
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent
|
||||
row={ row }
|
||||
column={ columns[1] }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ columnIndex }
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style target component correctly', () => {
|
||||
expect(wrapper.find('.react-bootstrap-table-editing-cell').prop('style')).toEqual(style);
|
||||
});
|
||||
|
||||
it('should call column.editCellStyle function correctly', () => {
|
||||
expect(columns[1].editCellStyle).toHaveBeenCalledTimes(1);
|
||||
expect(columns[1].editCellStyle).toHaveBeenCalledWith(
|
||||
_.get(row, columns[1].dataField),
|
||||
row,
|
||||
rowIndex,
|
||||
columnIndex
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
138
packages/react-bootstrap-table2-editor/test/row-consumer.test.js
Normal file
138
packages/react-bootstrap-table2-editor/test/row-consumer.test.js
Normal file
@@ -0,0 +1,138 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import _ from 'react-bootstrap-table-next/src/utils';
|
||||
import op from 'react-bootstrap-table-next/src/store/operators';
|
||||
|
||||
import cellEditFactory from '..';
|
||||
import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT, DELAY_FOR_DBCLICK } from '../src/const';
|
||||
import createCellEditContext from '../src/context';
|
||||
import withRowLevelCellEdit from '../src/row-consumer';
|
||||
|
||||
describe('Row Consumer', () => {
|
||||
let wrapper;
|
||||
let cellEdit;
|
||||
const data = [{
|
||||
id: 1,
|
||||
name: 'A'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'B'
|
||||
}];
|
||||
const row = { id: 1, name: 'A' };
|
||||
const keyField = 'id';
|
||||
const value = _.get(row, keyField);
|
||||
|
||||
const { Provider } = createCellEditContext(_, op, false, jest.fn());
|
||||
const BaseComponent = () => null;
|
||||
|
||||
describe('if cellEdit.nonEditableRows is undefined', () => {
|
||||
beforeEach(() => {
|
||||
const WithCellEditComponent = withRowLevelCellEdit(
|
||||
props => <BaseComponent { ...props } />,
|
||||
false
|
||||
);
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent value={ value } />
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject correct props to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('editingRowIdx')).toBeNull();
|
||||
expect(wrapper.find(BaseComponent).prop('editingColIdx')).toBeNull();
|
||||
expect(wrapper.find(BaseComponent).prop('editable')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if cellEdit.nonEditableRows is defined', () => {
|
||||
const nonEditableRows = jest.fn().mockReturnValue([value]);
|
||||
describe('if value prop is match in one of cellEdit.nonEditableRows', () => {
|
||||
beforeEach(() => {
|
||||
const WithCellEditComponent = withRowLevelCellEdit(
|
||||
props => <BaseComponent { ...props } />,
|
||||
false
|
||||
);
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT, nonEditableRows });
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent value={ value } />
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject correct editable prop as false to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('editable')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if value prop is not match in one of cellEdit.nonEditableRows', () => {
|
||||
beforeEach(() => {
|
||||
const WithCellEditComponent = withRowLevelCellEdit(
|
||||
props => <BaseComponent { ...props } />,
|
||||
false
|
||||
);
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT, nonEditableRows });
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent value={ 2 } />
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject correct editable prop as false to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('editable')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`if selectRowEnabled argument is true and cellEdit.mode is ${DBCLICK_TO_CELL_EDIT}`, () => {
|
||||
beforeEach(() => {
|
||||
const WithCellEditComponent = withRowLevelCellEdit(
|
||||
props => <BaseComponent { ...props } />,
|
||||
true
|
||||
);
|
||||
cellEdit = cellEditFactory({ mode: DBCLICK_TO_CELL_EDIT });
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent value={ value } />
|
||||
</Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject correct DELAY_FOR_DBCLICK prop to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('DELAY_FOR_DBCLICK')).toEqual(DELAY_FOR_DBCLICK);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if cellEdit.ridx and cellEdit.cidx are defined', () => {
|
||||
const ridx = 0;
|
||||
const cidx = 1;
|
||||
beforeEach(() => {
|
||||
const WithCellEditComponent = withRowLevelCellEdit(
|
||||
props => <BaseComponent { ...props } />,
|
||||
false
|
||||
);
|
||||
cellEdit = cellEditFactory({ mode: CLICK_TO_CELL_EDIT });
|
||||
wrapper = mount(
|
||||
<Provider data={ data } keyField={ keyField } cellEdit={ cellEdit }>
|
||||
<WithCellEditComponent value={ value } />
|
||||
</Provider>
|
||||
);
|
||||
wrapper.instance().startEditing(ridx, cidx);
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
it('should inject correct editable prop as false to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('editingRowIdx')).toEqual(ridx);
|
||||
expect(wrapper.find(BaseComponent).prop('editingColIdx')).toEqual(cidx);
|
||||
});
|
||||
});
|
||||
});
|
||||
182
packages/react-bootstrap-table2-example/examples/basic/exposed-function.js
vendored
Normal file
182
packages/react-bootstrap-table2-example/examples/basic/exposed-function.js
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/* eslint no-return-assign: 0 */
|
||||
/* eslint no-console: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator(63);
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true,
|
||||
filter: textFilter()
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
sort: true,
|
||||
filter: textFilter()
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
class ExposedFunctionTable extends React.Component {
|
||||
handleGetCurrentData = () => {
|
||||
console.log(this.node.table.props.data);
|
||||
}
|
||||
|
||||
handleGetSelectedData = () => {
|
||||
console.log(this.node.selectionContext.state.selected);
|
||||
}
|
||||
|
||||
handleGetExpandedData = () => {
|
||||
console.log(this.node.rowExpandContext.state.expanded);
|
||||
}
|
||||
|
||||
handleGetCurrentPage = () => {
|
||||
console.log(this.node.paginationContext.currPage);
|
||||
}
|
||||
|
||||
handleGetCurrentSizePerPage = () => {
|
||||
console.log(this.node.paginationContext.currSizePerPage);
|
||||
}
|
||||
|
||||
handleGetCurrentSortColumn = () => {
|
||||
console.log(this.node.sortContext.state.sortColumn);
|
||||
}
|
||||
|
||||
handleGetCurrentSortOrder = () => {
|
||||
console.log(this.node.sortContext.state.sortOrder);
|
||||
}
|
||||
|
||||
handleGetCurrentFilter = () => {
|
||||
console.log(this.node.filterContext.currFilters);
|
||||
}
|
||||
|
||||
render() {
|
||||
const expandRow = {
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>.....</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
),
|
||||
showExpandColumn: true
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentData }>Get Current Display Rows</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetSelectedData }>Get Current Selected Rows</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetExpandedData }>Get Current Expanded Rows</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentPage }>Get Current Page</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentSizePerPage }>Get Current Size Per Page</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentSortColumn }>Get Current Sort Column</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentSortOrder }>Get Current Sort Order</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentFilter }>Get Current Filter Information</button>
|
||||
<BootstrapTable
|
||||
ref={ n => this.node = n }
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
pagination={ paginationFactory() }
|
||||
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default class ExposedFunctionTable extends React.Component {
|
||||
handleGetCurrentData = () => {
|
||||
console.log(this.node.table.props.data);
|
||||
}
|
||||
|
||||
handleGetSelectedData = () => {
|
||||
console.log(this.node.selectionContext.state.selected);
|
||||
}
|
||||
|
||||
handleGetExpandedData = () => {
|
||||
console.log(this.node.rowExpandContext.state.expanded);
|
||||
}
|
||||
|
||||
handleGetCurrentPage = () => {
|
||||
console.log(this.node.paginationContext.currPage);
|
||||
}
|
||||
|
||||
handleGetCurrentSizePerPage = () => {
|
||||
console.log(this.node.paginationContext.currSizePerPage);
|
||||
}
|
||||
|
||||
handleGetCurrentSortColumn = () => {
|
||||
console.log(this.node.sortContext.state.sortColumn);
|
||||
}
|
||||
|
||||
handleGetCurrentSortOrder = () => {
|
||||
console.log(this.node.sortContext.state.sortOrder);
|
||||
}
|
||||
|
||||
handleGetCurrentFilter = () => {
|
||||
console.log(this.node.filterContext.currFilters);
|
||||
}
|
||||
|
||||
render() {
|
||||
const expandRow = {
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
),
|
||||
showExpandColumn: true
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentData }>Get Current Display Rows</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetSelectedData }>Get Current Selected Rows</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetExpandedData }>Get Current Expanded Rows</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentPage }>Get Current Page</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentSizePerPage }>Get Current Size Per Page</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentSortColumn }>Get Current Sort Column</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentSortOrder }>Get Current Sort Order</button>
|
||||
<button className="btn btn-default" onClick={ this.handleGetCurrentFilter }>Get Current Filter Information</button>
|
||||
<BootstrapTable
|
||||
ref={ n => this.node = n }
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
filter={ filterFactory() }
|
||||
pagination={ paginationFactory() }
|
||||
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator(5000);
|
||||
const products = productsGenerator(3000);
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
@@ -17,16 +16,25 @@ const columns = [{
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const expandRow = {
|
||||
showExpandColumn: true,
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ { mode: 'checkbox' } }
|
||||
cellEdit={ cellEditFactory({
|
||||
mode: 'click'
|
||||
}) }
|
||||
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
54
packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js
vendored
Normal file
54
packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ { mode: 'checkbox' } }
|
||||
tabIndexCell
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ { mode: 'checkbox' } }
|
||||
tabIndexCell
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
78
packages/react-bootstrap-table2-example/examples/cell-edit/auto-select-text-input-table.js
vendored
Normal file
78
packages/react-bootstrap-table2-example/examples/cell-edit/auto-select-text-input-table.js
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/* eslint react/prefer-stateless-function: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
|
||||
import Code from 'components/common/code-block';
|
||||
import { jobsGenerator } from 'utils/common';
|
||||
|
||||
const jobs = jobsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Job ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Job Name'
|
||||
}, {
|
||||
dataField: 'owner',
|
||||
text: 'Job Owner'
|
||||
}, {
|
||||
dataField: 'type',
|
||||
text: 'Job Type',
|
||||
editor: {
|
||||
type: Type.TEXTAREA
|
||||
}
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Job ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Job Name'
|
||||
}, {
|
||||
dataField: 'owner',
|
||||
text: 'Job Owner'
|
||||
}, {
|
||||
dataField: 'type',
|
||||
text: 'Job Type',
|
||||
editor: {
|
||||
type: Type.TEXTAREA
|
||||
}
|
||||
}];
|
||||
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ jobs }
|
||||
columns={ columns }
|
||||
cellEdit={
|
||||
cellEditFactory({
|
||||
mode: 'click',
|
||||
autoSelectText: true
|
||||
})
|
||||
}
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Auto Select Text Input Field When Editing</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ jobs }
|
||||
columns={ columns }
|
||||
cellEdit={
|
||||
cellEditFactory({
|
||||
mode: 'click',
|
||||
autoSelectText: true
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
@@ -41,6 +41,7 @@ const columns = [{
|
||||
columns={ columns }
|
||||
cellEdit={ cellEditFactory({
|
||||
mode: 'click',
|
||||
onStartEdit: (row, column, rowIndex, columnIndex) => { console.log('start to edit!!!'); },
|
||||
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
|
||||
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
|
||||
}) }
|
||||
@@ -55,6 +56,7 @@ export default () => (
|
||||
columns={ columns }
|
||||
cellEdit={ cellEditFactory({
|
||||
mode: 'click',
|
||||
onStartEdit: (row, column, rowIndex, columnIndex) => { console.log('Start to edit!!!'); },
|
||||
beforeSaveCell: (oldValue, newValue, row, column) => { console.log('Before Saving Cell!!'); },
|
||||
afterSaveCell: (oldValue, newValue, row, column) => { console.log('After Saving Cell!!'); }
|
||||
}) }
|
||||
|
||||
@@ -52,7 +52,7 @@ const columns = [{
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Dropdown Editor</h3>
|
||||
<h3>Checkbox Editor</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ todos }
|
||||
|
||||
@@ -118,7 +118,7 @@ const columns = [{
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Dropdown Editor</h3>
|
||||
<h3>Custom Editor</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
|
||||
@@ -65,7 +65,7 @@ const columns = [{
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Dropdown Editor</h3>
|
||||
<h3>Date Editor</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ stocks }
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToEdit: true
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory from 'react-bootstrap-table2-editor';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToEdit: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
cellEdit={ cellEditFactory({ mode: 'dbclick' }) }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Double click to edit cell</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
cellEdit={ cellEditFactory({ mode: 'dbclick' }) }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
@@ -56,7 +56,7 @@ const columns = [{
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Dropdown Editor</h3>
|
||||
<h3>Textarea Editor</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ jobs }
|
||||
|
||||
221
packages/react-bootstrap-table2-example/examples/columns/dummy-column-table.js
vendored
Normal file
221
packages/react-bootstrap-table2-example/examples/columns/dummy-column-table.js
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
/* eslint jsx-a11y/label-has-for: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
|
||||
|
||||
const products = [
|
||||
{ id: 12, name: 'Item 12', price: 12.5, inStock: false },
|
||||
{ id: 13, name: 'Item 13', price: 13.5, inStock: true },
|
||||
{ id: 14, name: 'Item 14', price: 14.5, inStock: true }
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
},
|
||||
{
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
},
|
||||
{
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
},
|
||||
{
|
||||
dataField: 'inStock',
|
||||
text: 'In Stock',
|
||||
formatter: (cellContent, row) => (
|
||||
<div className="checkbox disabled">
|
||||
<label>
|
||||
<input type="checkbox" checked={ row.inStock } disabled />
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
dataField: 'df1',
|
||||
isDummyField: true,
|
||||
text: 'Action 1',
|
||||
formatter: (cellContent, row) => {
|
||||
if (row.inStock) {
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-success"> Available</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-danger"> Backordered</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
dataField: 'df2',
|
||||
isDummyField: true,
|
||||
text: 'Action 2',
|
||||
formatter: (cellContent, row) => {
|
||||
if (row.inStock) {
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-success"> Available</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-danger"> Backordered</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
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'
|
||||
},
|
||||
{
|
||||
dataField: 'inStock',
|
||||
text: 'In Stock',
|
||||
formatter: (cellContent, row) => (
|
||||
<div className="checkbox disabled">
|
||||
<label>
|
||||
<input type="checkbox" checked={ row.inStock } disabled />
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
dataField: 'df1',
|
||||
isDummyField: true,
|
||||
text: 'Action 1',
|
||||
formatter: (cellContent, row) => {
|
||||
if (row.inStock) {
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-success"> Available</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-danger"> Backordered</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
dataField: 'df2',
|
||||
isDummyField: true,
|
||||
text: 'Action 2',
|
||||
formatter: (cellContent, row) => {
|
||||
if (row.inStock) {
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-success"> Available</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<h5>
|
||||
<span className="label label-danger"> Backordered</span>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
class ProductList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { products };
|
||||
}
|
||||
|
||||
toggleInStock = () => {
|
||||
let newProducts = [...this.state.products];
|
||||
newProducts = newProducts.map((d) => {
|
||||
if (d.id === 13) {
|
||||
return {
|
||||
...d,
|
||||
inStock: !d.inStock
|
||||
};
|
||||
}
|
||||
return d;
|
||||
});
|
||||
this.setState(curr => ({ ...curr, products: newProducts }));
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="h2">Products</h1>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ this.state.products }
|
||||
columns={ columns }
|
||||
/>
|
||||
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
||||
Toggle item 13 stock status
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
class ProductList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { products };
|
||||
}
|
||||
|
||||
toggleInStock = () => {
|
||||
let newProducts = [...this.state.products];
|
||||
newProducts = newProducts.map((d) => {
|
||||
if (d.id === 13) {
|
||||
return {
|
||||
...d,
|
||||
inStock: !d.inStock
|
||||
};
|
||||
}
|
||||
return d;
|
||||
});
|
||||
this.setState(curr => ({ ...curr, products: newProducts }));
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<h3>Action 1 and Action 2 are dummy column</h3>
|
||||
<button onClick={ this.toggleInStock } className="btn btn-primary">
|
||||
Toggle item 13 stock status
|
||||
</button>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ this.state.products }
|
||||
columns={ columns }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ProductList;
|
||||
98
packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js
vendored
Normal file
98
packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const MyExportCSV = (props) => {
|
||||
const handleClick = () => {
|
||||
props.onExport();
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button className="btn btn-success" onClick={ handleClick }>Export to CSV</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
exportCSV
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<BootstrapTable { ...props.baseProps } />
|
||||
<hr />
|
||||
<MyExportCSV { ...props.csvProps } />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
`;
|
||||
|
||||
const MyExportCSV = (props) => {
|
||||
const handleClick = () => {
|
||||
// passing my custom data
|
||||
props.onExport(products.filter(r => r.id > 2));
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<button className="btn btn-success" onClick={ handleClick }>Only export Product ID bigger than 2</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
exportCSV
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<BootstrapTable { ...props.baseProps } />
|
||||
<hr />
|
||||
<MyExportCSV { ...props.csvProps } />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
140
packages/react-bootstrap-table2-example/examples/csv/export-only-selected.js
vendored
Normal file
140
packages/react-bootstrap-table2-example/examples/csv/export-only-selected.js
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider, { CSVExport } from 'react-bootstrap-table2-toolkit';
|
||||
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const { ExportCSVButton } = CSVExport;
|
||||
const products1 = productsGenerator(15);
|
||||
const products2 = productsGenerator(15);
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider, { CSVExport } from 'react-bootstrap-table2-toolkit';
|
||||
|
||||
const { ExportCSVButton } = CSVExport;
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products1 }
|
||||
columns={ columns }
|
||||
exportCSV={ { onlyExportSelection: true, exportAll: true } }
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||
<hr />
|
||||
<BootstrapTable
|
||||
{ ...props.baseProps }
|
||||
selectRow={ selectRow }
|
||||
pagination={ paginationFactory() }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products2 }
|
||||
columns={ columns }
|
||||
exportCSV={ { onlyExportSelection: true, exportAll: false } }
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||
<hr />
|
||||
<BootstrapTable
|
||||
{ ...props.baseProps }
|
||||
selectRow={ selectRow }
|
||||
pagination={ paginationFactory() }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
`;
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Export all selected row</h3>
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products1 }
|
||||
columns={ columns }
|
||||
exportCSV={ { onlyExportSelection: true, exportAll: true } }
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||
<hr />
|
||||
<BootstrapTable
|
||||
{ ...props.baseProps }
|
||||
selectRow={ selectRow }
|
||||
pagination={ paginationFactory() }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
<h3>Export all selected rows in currect visible rows</h3>
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products2 }
|
||||
columns={ columns }
|
||||
exportCSV={ { onlyExportSelection: true, exportAll: false } }
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
|
||||
<hr />
|
||||
<BootstrapTable
|
||||
{ ...props.baseProps }
|
||||
selectRow={ selectRow }
|
||||
pagination={ paginationFactory() }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
76
packages/react-bootstrap-table2-example/examples/row-expand/expand-by-column-only.js
vendored
Normal file
76
packages/react-bootstrap-table2-example/examples/row-expand/expand-by-column-only.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsExpandRowsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsExpandRowsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const expandRow = {
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
),
|
||||
showExpandColumn: true,
|
||||
expandByColumnOnly: true
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const expandRow = {
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
),
|
||||
showExpandColumn: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Only able to expand row via clicking expand column(indicator)</h3>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
73
packages/react-bootstrap-table2-example/examples/row-expand/expand-only-one.js
vendored
Normal file
73
packages/react-bootstrap-table2-example/examples/row-expand/expand-only-one.js
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsExpandRowsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsExpandRowsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const expandRow = {
|
||||
onlyOneExpanding: true,
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const expandRow = {
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
59
packages/react-bootstrap-table2-example/examples/row-selection/hide-select-all.js
vendored
Normal file
59
packages/react-bootstrap-table2-example/examples/row-selection/hide-select-all.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
hideSelectAll: true
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
hideSelectAll: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-with-expansion.js
vendored
Normal file
88
packages/react-bootstrap-table2-example/examples/row-selection/selection-with-expansion.js
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToExpand: true
|
||||
};
|
||||
|
||||
const expandRow = {
|
||||
showExpandColumn: true,
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToExpand: true
|
||||
};
|
||||
|
||||
const expandRow = {
|
||||
showExpandColumn: true,
|
||||
renderer: row => (
|
||||
<div>
|
||||
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
/* eslint no-alert: 0 */
|
||||
/* eslint no-console: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
@@ -21,7 +21,10 @@ const columns = [{
|
||||
|
||||
const rowEvents = {
|
||||
onClick: (e, row, rowIndex) => {
|
||||
alert(`clicked on row with index: ${rowIndex}`);
|
||||
console.log(`clicked on row with index: ${rowIndex}`);
|
||||
},
|
||||
onMouseEnter: (e, row, rowIndex) => {
|
||||
console.log(`enter on row with index: ${rowIndex}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,7 +44,10 @@ const columns = [{
|
||||
|
||||
const rowEvents = {
|
||||
onClick: (e, row, rowIndex) => {
|
||||
alert(\`clicked on row with index: \${rowIndex}\`);
|
||||
console.log(\`clicked on row with index: \${rowIndex}\`);
|
||||
},
|
||||
onMouseEnter: (e, row, rowIndex) => {
|
||||
console.log(\`enter on row with index: \${rowIndex}\`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,7 +56,7 @@ const rowEvents = {
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h3>Try to click on any rows</h3>
|
||||
<h3>Try to click or hover on any rows</h3>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } rowEvents={ rowEvents } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
|
||||
83
packages/react-bootstrap-table2-example/examples/search/default-search.js
vendored
Normal file
83
packages/react-bootstrap-table2-example/examples/search/default-search.js
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const { SearchBar } = Search;
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
|
||||
|
||||
const { SearchBar } = Search;
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
search={ { defaultSearch: '2101' } }
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<h3>Input something at below input field:</h3>
|
||||
<SearchBar { ...props.searchProps } />
|
||||
<hr />
|
||||
<BootstrapTable
|
||||
{ ...props.baseProps }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
search={ { defaultSearch: '2101' } }
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<div>
|
||||
<h3>Input something at below input field:</h3>
|
||||
<SearchBar { ...props.searchProps } />
|
||||
<hr />
|
||||
<BootstrapTable
|
||||
{ ...props.baseProps }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
59
packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js
vendored
Normal file
59
packages/react-bootstrap-table2-example/examples/sort/custom-sort-caret.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/* eslint no-unused-vars: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true,
|
||||
sortCaret: (order, column) => {
|
||||
if (!order) return (<span> Desc/Asc</span>);
|
||||
else if (order === 'asc') return (<span> Desc/<font color="red">Asc</font></span>);
|
||||
else if (order === 'desc') return (<span> <font color="red">Desc</font>/Asc</span>);
|
||||
return null;
|
||||
}
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const sourceCode = `\
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
sort: true
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true,
|
||||
sortCaret: (order, column) => {
|
||||
if (!order) return (<span> Desc/Asc</span>);
|
||||
else if (order === 'asc') return (<span> Desc/<font color="red">Asc</font></span>);
|
||||
else if (order === 'desc') return (<span> <font color="red">Desc</font>/Asc</span>);
|
||||
return null;
|
||||
}
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
<BootstrapTable keyField='id' data={ products } columns={ columns } />
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import Typed from 'typed.js';
|
||||
|
||||
const PROJECT_NAME = 'react-bootstrap-table2';
|
||||
|
||||
export default class Welcome extends React.Component {
|
||||
componentDidMount() {
|
||||
// type.js config
|
||||
@@ -21,14 +23,21 @@ export default class Welcome extends React.Component {
|
||||
return (
|
||||
<div>
|
||||
<div className="welcome">
|
||||
<h1 className="welcome-title">react-bootstrap-table2</h1>
|
||||
<div className="welcome-title">
|
||||
<span className="welcome-title-logo">
|
||||
<img src="images/logo-color-square.svg" alt={ `${PROJECT_NAME}-logo` } />
|
||||
</span>
|
||||
<h1>
|
||||
{PROJECT_NAME}
|
||||
</h1>
|
||||
</div>
|
||||
<span
|
||||
className="welcome-sub-title"
|
||||
ref={ (el) => { this.el = el; } }
|
||||
/>
|
||||
</div>
|
||||
<a href="https://github.com/react-bootstrap-table/react-bootstrap-table2" className="github-corner" aria-label="View source on Github">
|
||||
<svg width="80" height="80" viewBox="0 0 250 250" style={ { fill: '#009688', color: '#fff', position: 'absolute', top: '0', border: '0', right: '0' } } aria-hidden="true">
|
||||
<a href={ `https://github.com/react-bootstrap-table/${PROJECT_NAME}` } className="github-corner" aria-label="View source on Github">
|
||||
<svg width="80" height="80" viewBox="0 0 250 250" style={ { fill: '#0058B7', color: '#fff', position: 'absolute', top: '0', border: '0', right: '0' } } aria-hidden="true">
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
|
||||
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style={ { transformOrigin: '130px 106px' } } className="octo-arm" />
|
||||
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" className="octo-body" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-example",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.7",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
@@ -15,7 +15,7 @@
|
||||
"peerDependencies": {
|
||||
"prop-types": "^15.0.0",
|
||||
"react": "^16.3.0",
|
||||
"react-dom": "^116.3.0"
|
||||
"react-dom": "^16.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-console": "^1.0.0",
|
||||
|
||||
BIN
packages/react-bootstrap-table2-example/public/favicon.ico
Normal file
BIN
packages/react-bootstrap-table2-example/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="layer_1" data-name="layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72"><defs><style>.cls-1{fill:#059ae6;}.cls-2{fill:#0058b7;}</style></defs><title>logo square</title><polygon class="cls-1" points="22.76 59 22.76 64.35 49.24 51.13 49.24 43.88 44.45 41.5 44.45 48.17 22.76 59"/><polygon class="cls-2" points="22.76 20.87 22.76 47.98 27.55 45.59 27.55 23.83 44.45 15.39 44.45 23.02 33.06 28.71 33.06 31.9 49.24 39.97 49.24 34.62 40.58 30.3 49.24 25.98 49.24 7.65 22.76 20.87"/></svg>
|
||||
|
After Width: | Height: | Size: 503 B |
@@ -13,6 +13,8 @@ import NoDataTable from 'examples/basic/no-data-table';
|
||||
import CustomizedIdClassesTable from 'examples/basic/customized-id-classes';
|
||||
import CaptionTable from 'examples/basic/caption-table';
|
||||
import LargeTable from 'examples/basic/large-table';
|
||||
import ExposedAPITable from 'examples/basic/exposed-function';
|
||||
import TabIndexCellTable from 'examples/basic/tabindex-column';
|
||||
|
||||
// bootstrap 4
|
||||
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
|
||||
@@ -30,6 +32,7 @@ import ColumnTitleTable from 'examples/columns/column-title-table';
|
||||
import ColumnEventTable from 'examples/columns/column-event-table';
|
||||
import ColumnHiddenTable from 'examples/columns/column-hidden-table';
|
||||
import ColumnAttrsTable from 'examples/columns/column-attrs-table';
|
||||
import DummyColumnTable from 'examples/columns/dummy-column-table';
|
||||
|
||||
// work on header columns
|
||||
import HeaderColumnFormatTable from 'examples/header-columns/column-format-table';
|
||||
@@ -82,6 +85,7 @@ import DefaultSortTable from 'examples/sort/default-sort-table';
|
||||
import DefaultSortDirectionTable from 'examples/sort/default-sort-direction';
|
||||
import SortEvents from 'examples/sort/sort-events';
|
||||
import CustomSortTable from 'examples/sort/custom-sort-table';
|
||||
import CustomSortCaretTable from 'examples/sort/custom-sort-caret';
|
||||
import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes';
|
||||
import HeaderSortingStyleTable from 'examples/sort/header-sorting-style';
|
||||
|
||||
@@ -96,8 +100,10 @@ import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
|
||||
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
|
||||
import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table';
|
||||
import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table';
|
||||
import AutoSelectTextInput from 'examples/cell-edit/auto-select-text-input-table';
|
||||
import EditorStyleTable from 'examples/cell-edit/editor-style-table';
|
||||
import EditorClassTable from 'examples/cell-edit/editor-class-table';
|
||||
import DBClickEditWithSelection from 'examples/cell-edit/dbclick-to-edit-with-selection-table';
|
||||
import DropdownEditorTable from 'examples/cell-edit/dropdown-editor-table';
|
||||
import TextareaEditorTable from 'examples/cell-edit/textarea-editor-table';
|
||||
import CheckboxEditorTable from 'examples/cell-edit/checkbox-editor-table';
|
||||
@@ -111,9 +117,11 @@ import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
||||
import DefaultSelectTable from 'examples/row-selection/default-select';
|
||||
import SelectionManagement from 'examples/row-selection/selection-management';
|
||||
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
||||
import SelectionWithExpansionTable from 'examples/row-selection/selection-with-expansion';
|
||||
import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
|
||||
import SelectionStyleTable from 'examples/row-selection/selection-style';
|
||||
import SelectionClassTable from 'examples/row-selection/selection-class';
|
||||
import HideSelectAllTable from 'examples/row-selection/hide-select-all';
|
||||
import CustomSelectionTable from 'examples/row-selection/custom-selection';
|
||||
import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows';
|
||||
import SelectionBgColorTable from 'examples/row-selection/selection-bgcolor';
|
||||
@@ -125,6 +133,8 @@ import BasicRowExpand from 'examples/row-expand';
|
||||
import RowExpandManagement from 'examples/row-expand/expand-management';
|
||||
import NonExpandableRows from 'examples/row-expand/non-expandable-rows';
|
||||
import ExpandColumn from 'examples/row-expand/expand-column';
|
||||
import OnlyExpandByColumn from 'examples/row-expand/expand-by-column-only.js';
|
||||
import ExpandOnlyOne from 'examples/row-expand/expand-only-one';
|
||||
import CustomExpandColumn from 'examples/row-expand/custom-expand-column';
|
||||
import ExpandHooks from 'examples/row-expand/expand-hooks';
|
||||
|
||||
@@ -135,6 +145,7 @@ import CustomPaginationTable from 'examples/pagination/custom-pagination';
|
||||
|
||||
// search
|
||||
import SearchTable from 'examples/search';
|
||||
import DefaultSearch from 'examples/search/default-search';
|
||||
import DefaultCustomSearch from 'examples/search/default-custom-search';
|
||||
import FullyCustomSearch from 'examples/search/fully-custom-search';
|
||||
import SearchFormattedData from 'examples/search/search-formatted';
|
||||
@@ -145,8 +156,10 @@ import ExportCSV from 'examples/csv';
|
||||
import CSVFormatter from 'examples/csv/csv-column-formatter';
|
||||
import CustomCSVHeader from 'examples/csv/custom-csv-header';
|
||||
import HideCSVColumn from 'examples/csv/hide-column';
|
||||
import ExportOnlySelected from 'examples/csv/export-only-selected';
|
||||
import CSVColumnType from 'examples/csv/csv-column-type';
|
||||
import CustomCSVButton from 'examples/csv/custom-csv-button';
|
||||
import ExportCustomData from 'examples/csv/export-custom-data';
|
||||
import CustomCSV from 'examples/csv/custom-csv';
|
||||
|
||||
// loading overlay
|
||||
@@ -182,7 +195,9 @@ storiesOf('Basic Table', module)
|
||||
.add('Indication For Empty Table', () => <NoDataTable />)
|
||||
.add('Customized id and class table', () => <CustomizedIdClassesTable />)
|
||||
.add('Table with caption', () => <CaptionTable />)
|
||||
.add('Large Table', () => <LargeTable />);
|
||||
.add('Large Table', () => <LargeTable />)
|
||||
.add('Exposed API', () => <ExposedAPITable />)
|
||||
.add('Enable tabIndex on Cell', () => <TabIndexCellTable />);
|
||||
|
||||
storiesOf('Bootstrap 4', module)
|
||||
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
|
||||
@@ -201,7 +216,8 @@ storiesOf('Work on Columns', module)
|
||||
.add('Column Event', () => <ColumnEventTable />)
|
||||
.add('Customize Column Class', () => <ColumnClassTable />)
|
||||
.add('Customize Column Style', () => <ColumnStyleTable />)
|
||||
.add('Customize Column HTML attribute', () => <ColumnAttrsTable />);
|
||||
.add('Customize Column HTML attribute', () => <ColumnAttrsTable />)
|
||||
.add('Dummy Column', () => <DummyColumnTable />);
|
||||
|
||||
storiesOf('Work on Header Columns', module)
|
||||
.addDecorator(bootstrapStyle())
|
||||
@@ -259,6 +275,7 @@ storiesOf('Sort Table', module)
|
||||
.add('Default Sort Direction Table', () => <DefaultSortDirectionTable />)
|
||||
.add('Sort Events', () => <SortEvents />)
|
||||
.add('Custom Sort Fuction', () => <CustomSortTable />)
|
||||
.add('Custom Sort Caret', () => <CustomSortCaretTable />)
|
||||
.add('Custom Classes on Sorting Header Column', () => <HeaderSortingClassesTable />)
|
||||
.add('Custom Style on Sorting Header Column', () => <HeaderSortingStyleTable />);
|
||||
|
||||
@@ -272,10 +289,12 @@ storiesOf('Cell Editing', module)
|
||||
.add('Cell Level Editable', () => <CellLevelEditable />)
|
||||
.add('Rich Hook Functions', () => <CellEditHooks />)
|
||||
.add('Validation', () => <CellEditValidator />)
|
||||
.add('Auto Select Text Input', () => <AutoSelectTextInput />)
|
||||
.add('Custom Cell Style', () => <CellEditStyleTable />)
|
||||
.add('Custom Cell Classes', () => <CellEditClassTable />)
|
||||
.add('Custom Editor Classes', () => <EditorClassTable />)
|
||||
.add('Custom Editor Style', () => <EditorStyleTable />)
|
||||
.add('DoubleClick to Edit with Selection', () => <DBClickEditWithSelection />)
|
||||
.add('Dropdown Editor', () => <DropdownEditorTable />)
|
||||
.add('Textarea Editor', () => <TextareaEditorTable />)
|
||||
.add('Checkbox Editor', () => <CheckboxEditorTable />)
|
||||
@@ -290,9 +309,11 @@ storiesOf('Row Selection', module)
|
||||
.add('Default Select', () => <DefaultSelectTable />)
|
||||
.add('Selection Management', () => <SelectionManagement />)
|
||||
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
||||
.add('Row Select and Expand', () => <SelectionWithExpansionTable />)
|
||||
.add('Selection without Data', () => <SelectionNoDataTable />)
|
||||
.add('Selection Style', () => <SelectionStyleTable />)
|
||||
.add('Selection Class', () => <SelectionClassTable />)
|
||||
.add('Hide Select All', () => <HideSelectAllTable />)
|
||||
.add('Custom Selection', () => <CustomSelectionTable />)
|
||||
.add('Selection Background Color', () => <SelectionBgColorTable />)
|
||||
.add('Not Selectabled Rows', () => <NonSelectableRowsTable />)
|
||||
@@ -305,6 +326,8 @@ storiesOf('Row Expand', module)
|
||||
.add('Expand Management', () => <RowExpandManagement />)
|
||||
.add('Non Expandabled Rows', () => <NonExpandableRows />)
|
||||
.add('Expand Indicator', () => <ExpandColumn />)
|
||||
.add('Only Expand by Indicator', () => <OnlyExpandByColumn />)
|
||||
.add('Expand Only One Row at The Same Time', () => <ExpandOnlyOne />)
|
||||
.add('Custom Expand Indicator', () => <CustomExpandColumn />)
|
||||
.add('Expand Hooks', () => <ExpandHooks />);
|
||||
|
||||
@@ -317,6 +340,7 @@ storiesOf('Pagination', module)
|
||||
storiesOf('Table Search', module)
|
||||
.addDecorator(bootstrapStyle())
|
||||
.add('Basic Search Table', () => <SearchTable />)
|
||||
.add('Default Search Table', () => <DefaultSearch />)
|
||||
.add('Default Custom Search', () => <DefaultCustomSearch />)
|
||||
.add('Fully Custom Search', () => <FullyCustomSearch />)
|
||||
.add('Search Fromatted Value', () => <SearchFormattedData />)
|
||||
@@ -328,8 +352,10 @@ storiesOf('Export CSV', module)
|
||||
.add('Format CSV Column', () => <CSVFormatter />)
|
||||
.add('Custom CSV Header', () => <CustomCSVHeader />)
|
||||
.add('Hide CSV Column', () => <HideCSVColumn />)
|
||||
.add('Only Export Selected Rows', () => <ExportOnlySelected />)
|
||||
.add('CSV Column Type', () => <CSVColumnType />)
|
||||
.add('Custom CSV Button', () => <CustomCSVButton />)
|
||||
.add('Export Custom Data', () => <ExportCustomData />)
|
||||
.add('Custom CSV', () => <CustomCSV />);
|
||||
|
||||
storiesOf('EmptyTableOverlay', module)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
$logo-size: 96px;
|
||||
|
||||
.welcome {
|
||||
margin-top: 70px;
|
||||
text-align: center;
|
||||
@@ -5,7 +7,22 @@
|
||||
|
||||
&-title {
|
||||
color: $grey-900;
|
||||
width: 100%;
|
||||
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
|
||||
&-logo {
|
||||
position: relative;
|
||||
top: -8px;
|
||||
right: -12px;
|
||||
|
||||
width: $logo-size;
|
||||
height: $logo-size;
|
||||
}
|
||||
}
|
||||
|
||||
&-sub-title {
|
||||
font-size: 30px;
|
||||
color: $grey-500;
|
||||
|
||||
@@ -288,3 +288,4 @@ Following properties is valid in `FILTER_TYPES`:
|
||||
* SELECT
|
||||
* NUMBER
|
||||
* DATE
|
||||
* MULTISELECT
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-filter",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "it's a column filter addon for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-paginator",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"description": "it's the pagination addon for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -68,6 +68,9 @@ export default (
|
||||
currPage = newPage;
|
||||
needNewState = true;
|
||||
}
|
||||
} else {
|
||||
this.currPage = nextProps.pagination.options.page;
|
||||
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
|
||||
}
|
||||
|
||||
if (needNewState) {
|
||||
|
||||
@@ -160,6 +160,27 @@ describe('PaginationContext', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when remote pagination is enable', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({ ...defaultPagination }, true));
|
||||
instance = wrapper.instance();
|
||||
wrapper.render();
|
||||
nextProps = {
|
||||
data,
|
||||
pagination: { ...defaultPagination, options: { page: 3, sizePerPage: 5 } }
|
||||
};
|
||||
instance.componentWillReceiveProps(nextProps);
|
||||
});
|
||||
|
||||
it('should always set currPage from nextProps.pagination.options.page', () => {
|
||||
expect(instance.currPage).toEqual(nextProps.pagination.options.page);
|
||||
});
|
||||
|
||||
it('should always set currSizePerPage from nextProps.pagination.options.sizePerPage', () => {
|
||||
expect(instance.currSizePerPage).toEqual(nextProps.pagination.options.sizePerPage);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when page is not align', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
|
||||
@@ -63,6 +63,22 @@ const { SearchBar } = Search;
|
||||
|
||||
### Search Options
|
||||
|
||||
#### defaultSearch - [string]
|
||||
Accept a string that will be used for default searching when first time table render.
|
||||
|
||||
```js
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
search={ {
|
||||
defaultSearch: 'search something here'
|
||||
} }
|
||||
>
|
||||
// ...
|
||||
</ToolkitProvider>
|
||||
```
|
||||
|
||||
#### searchFormatted - [bool]
|
||||
If you want to search on the formatted data, you are supposed to enable this props. `react-bootstrap-table2` will check if you define the `column.formatter` when doing search.
|
||||
|
||||
@@ -124,3 +140,6 @@ Default is `true`.
|
||||
|
||||
#### exportAll - [bool]
|
||||
Default is `true`. `false` will only export current data which display on table.
|
||||
|
||||
#### onlyExportSelection - [bool]
|
||||
Default is `false`. `true` will only export the data which is selected.
|
||||
@@ -17,6 +17,7 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
||||
search: PropTypes.oneOfType([
|
||||
PropTypes.bool,
|
||||
PropTypes.shape({
|
||||
defaultSearch: PropTypes.string,
|
||||
searchFormatted: PropTypes.bool
|
||||
})
|
||||
]),
|
||||
@@ -26,7 +27,9 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
||||
fileName: PropTypes.string,
|
||||
separator: PropTypes.string,
|
||||
ignoreHeader: PropTypes.bool,
|
||||
noAutoBOM: PropTypes.bool
|
||||
noAutoBOM: PropTypes.bool,
|
||||
exportAll: PropTypes.bool,
|
||||
onlyExportSelection: PropTypes.bool
|
||||
})
|
||||
])
|
||||
}
|
||||
@@ -40,7 +43,7 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
searchText: ''
|
||||
searchText: typeof props.search === 'object' ? (props.search.defaultSearch || '') : ''
|
||||
};
|
||||
this._ = null;
|
||||
this.onSearch = this.onSearch.bind(this);
|
||||
@@ -83,6 +86,7 @@ class ToolkitProvider extends statelessDrcorator(React.Component) {
|
||||
return (
|
||||
<ToolkitContext.Provider value={ {
|
||||
searchProps: {
|
||||
searchText: this.state.searchText,
|
||||
onSearch: this.onSearch
|
||||
},
|
||||
csvProps: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table2-toolkit",
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.1",
|
||||
"description": "The toolkit for react-bootstrap-table2",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -11,7 +11,7 @@ const ExportCSVButton = (props) => {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={ onExport }
|
||||
onClick={ () => onExport() }
|
||||
{ ...rest }
|
||||
>
|
||||
{ children }
|
||||
|
||||
@@ -58,7 +58,7 @@ export const save = (
|
||||
}
|
||||
) => {
|
||||
FileSaver.saveAs(
|
||||
new Blob(['\ufeff', content], { type: 'text/plain;charset=utf-8' }),
|
||||
new Blob([content], { type: 'text/plain;charset=utf-8' }),
|
||||
fileName,
|
||||
noAutoBOM
|
||||
);
|
||||
|
||||
@@ -5,13 +5,14 @@ const csvDefaultOptions = {
|
||||
separator: ',',
|
||||
ignoreHeader: false,
|
||||
noAutoBOM: true,
|
||||
exportAll: true
|
||||
exportAll: true,
|
||||
onlyExportSelection: false
|
||||
};
|
||||
|
||||
export default Base =>
|
||||
class CSVOperation extends Base {
|
||||
handleExportCSV = () => {
|
||||
const { columns, exportCSV } = this.props;
|
||||
handleExportCSV = (source) => {
|
||||
const { columns, exportCSV, keyField } = this.props;
|
||||
const meta = getMetaInfo(columns);
|
||||
const options = exportCSV === true ?
|
||||
csvDefaultOptions :
|
||||
@@ -20,7 +21,19 @@ export default Base =>
|
||||
...exportCSV
|
||||
};
|
||||
|
||||
const data = options.exportAll ? this.props.data : this.getData();
|
||||
// get data for csv export
|
||||
let data;
|
||||
if (typeof source !== 'undefined') {
|
||||
data = source;
|
||||
} else {
|
||||
data = options.exportAll ? this.props.data : this.getData();
|
||||
}
|
||||
|
||||
// filter data
|
||||
if (options.onlyExportSelection) {
|
||||
const selections = this.getSelected();
|
||||
data = data.filter(row => !!selections.find(sel => row[keyField] === sel));
|
||||
}
|
||||
const content = transform(data, meta, this._.get, options);
|
||||
save(content, options);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ const SearchBar = ({
|
||||
style={ style }
|
||||
onKeyUp={ () => debounceCallback() }
|
||||
className={ `form-control ${className}` }
|
||||
defaultValue={ searchText }
|
||||
placeholder={ placeholder || SearchBar.defaultProps.placeholder }
|
||||
{ ...rest }
|
||||
/>
|
||||
|
||||
@@ -39,8 +39,10 @@ export default (options = {
|
||||
const { data, columns } = this.props;
|
||||
let { searchText } = this.props;
|
||||
|
||||
if (isRemoteSearch() && this.performRemoteSearch) {
|
||||
handleRemoteSearchChange(searchText);
|
||||
if (isRemoteSearch()) {
|
||||
if (this.performRemoteSearch) {
|
||||
handleRemoteSearchChange(searchText);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-bootstrap-table-next",
|
||||
"version": "1.1.3",
|
||||
"version": "1.3.0",
|
||||
"description": "Next generation of react-bootstrap-table",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
|
||||
199
packages/react-bootstrap-table2/src/body.js
vendored
199
packages/react-bootstrap-table2/src/body.js
vendored
@@ -3,129 +3,106 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cs from 'classnames';
|
||||
|
||||
import _ from './utils';
|
||||
import Row from './row';
|
||||
import ExpandRow from './row-expand/expand-row';
|
||||
import RowSection from './row-section';
|
||||
import SimpleRow from './row/simple-row';
|
||||
import RowAggregator from './row/aggregate-row';
|
||||
import RowSection from './row/row-section';
|
||||
import Const from './const';
|
||||
import withRowSelection from './row-selection/row-consumer';
|
||||
import withRowExpansion from './row-expand/row-consumer';
|
||||
|
||||
const Body = (props) => {
|
||||
const {
|
||||
columns,
|
||||
data,
|
||||
keyField,
|
||||
isEmpty,
|
||||
noDataIndication,
|
||||
visibleColumnSize,
|
||||
cellEdit,
|
||||
selectRow,
|
||||
selectedRowKeys,
|
||||
rowStyle,
|
||||
rowClasses,
|
||||
rowEvents,
|
||||
expandRow
|
||||
} = props;
|
||||
|
||||
const {
|
||||
bgColor,
|
||||
nonSelectable
|
||||
} = selectRow;
|
||||
|
||||
let content;
|
||||
|
||||
if (isEmpty) {
|
||||
const indication = _.isFunction(noDataIndication) ? noDataIndication() : noDataIndication;
|
||||
if (!indication) {
|
||||
return null;
|
||||
class Body extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
if (props.cellEdit.createContext) {
|
||||
this.EditingCell = props.cellEdit.createEditingCell(_, props.cellEdit.options.onStartEdit);
|
||||
}
|
||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||
} else {
|
||||
const nonEditableRows = cellEdit.nonEditableRows || [];
|
||||
content = data.map((row, index) => {
|
||||
const key = _.get(row, keyField);
|
||||
const editable = !(nonEditableRows.length > 0 && nonEditableRows.indexOf(key) > -1);
|
||||
|
||||
const selected = selectRow.mode !== Const.ROW_SELECT_DISABLED
|
||||
? selectedRowKeys.includes(key)
|
||||
: null;
|
||||
|
||||
const attrs = rowEvents || {};
|
||||
let style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
||||
let classes = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
||||
if (selected) {
|
||||
const selectedStyle = _.isFunction(selectRow.style)
|
||||
? selectRow.style(row, index)
|
||||
: selectRow.style;
|
||||
|
||||
const selectedClasses = _.isFunction(selectRow.classes)
|
||||
? selectRow.classes(row, index)
|
||||
: selectRow.classes;
|
||||
|
||||
style = {
|
||||
...style,
|
||||
...selectedStyle
|
||||
};
|
||||
classes = cs(classes, selectedClasses);
|
||||
|
||||
if (bgColor) {
|
||||
style = style || {};
|
||||
style.backgroundColor = _.isFunction(bgColor) ? bgColor(row, index) : bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
const selectable = !nonSelectable || !nonSelectable.includes(key);
|
||||
const expandable = expandRow && !expandRow.nonExpandable.includes(key);
|
||||
const expanded = expandRow && expandRow.expanded.includes(key);
|
||||
|
||||
const result = [
|
||||
<Row
|
||||
key={ key }
|
||||
row={ row }
|
||||
keyField={ keyField }
|
||||
rowIndex={ index }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
editable={ editable }
|
||||
selectable={ selectable }
|
||||
expandable={ expandable }
|
||||
selected={ selected }
|
||||
expanded={ expanded }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
style={ style }
|
||||
className={ classes }
|
||||
attrs={ attrs }
|
||||
/>
|
||||
];
|
||||
|
||||
if (expanded) {
|
||||
result.push((
|
||||
<ExpandRow
|
||||
key={ `${key}-expanding` }
|
||||
colSpan={ visibleColumnSize }
|
||||
>
|
||||
{ expandRow.renderer(row) }
|
||||
</ExpandRow>
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<tbody>{ content }</tbody>
|
||||
);
|
||||
};
|
||||
render() {
|
||||
const {
|
||||
columns,
|
||||
data,
|
||||
tabIndexCell,
|
||||
keyField,
|
||||
isEmpty,
|
||||
noDataIndication,
|
||||
visibleColumnSize,
|
||||
cellEdit,
|
||||
selectRow,
|
||||
rowStyle,
|
||||
rowClasses,
|
||||
rowEvents,
|
||||
expandRow
|
||||
} = this.props;
|
||||
|
||||
let content;
|
||||
|
||||
if (isEmpty) {
|
||||
const indication = _.isFunction(noDataIndication) ? noDataIndication() : noDataIndication;
|
||||
if (!indication) {
|
||||
return null;
|
||||
}
|
||||
content = <RowSection content={ indication } colSpan={ visibleColumnSize } />;
|
||||
} else {
|
||||
let RowComponent = SimpleRow;
|
||||
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
|
||||
const expandRowEnabled = !!expandRow.renderer;
|
||||
|
||||
const additionalRowProps = {};
|
||||
if (expandRowEnabled) {
|
||||
RowComponent = withRowExpansion(RowAggregator, visibleColumnSize);
|
||||
}
|
||||
|
||||
if (selectRowEnabled) {
|
||||
RowComponent = withRowSelection(expandRowEnabled ? RowComponent : RowAggregator);
|
||||
}
|
||||
|
||||
if (cellEdit.createContext) {
|
||||
RowComponent = cellEdit.withRowLevelCellEdit(RowComponent, selectRowEnabled, keyField, _);
|
||||
additionalRowProps.EditingCellComponent = this.EditingCell;
|
||||
}
|
||||
|
||||
if (selectRowEnabled || expandRowEnabled) {
|
||||
additionalRowProps.expandRow = expandRow;
|
||||
additionalRowProps.selectRow = selectRow;
|
||||
}
|
||||
|
||||
content = data.map((row, index) => {
|
||||
const key = _.get(row, keyField);
|
||||
const baseRowProps = {
|
||||
key,
|
||||
row,
|
||||
tabIndexCell,
|
||||
columns,
|
||||
keyField,
|
||||
cellEdit,
|
||||
value: key,
|
||||
rowIndex: index,
|
||||
visibleColumnSize,
|
||||
attrs: rowEvents || {},
|
||||
...additionalRowProps
|
||||
};
|
||||
|
||||
baseRowProps.style = _.isFunction(rowStyle) ? rowStyle(row, index) : rowStyle;
|
||||
baseRowProps.className = (_.isFunction(rowClasses) ? rowClasses(row, index) : rowClasses);
|
||||
|
||||
return <RowComponent { ...baseRowProps } />;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<tbody>{ content }</tbody>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Body.propTypes = {
|
||||
keyField: PropTypes.string.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
columns: PropTypes.array.isRequired,
|
||||
selectRow: PropTypes.object,
|
||||
selectedRowKeys: PropTypes.array
|
||||
selectRow: PropTypes.object
|
||||
};
|
||||
|
||||
export default Body;
|
||||
|
||||
@@ -9,7 +9,6 @@ import Caption from './caption';
|
||||
import Body from './body';
|
||||
import PropsBaseResolver from './props-resolver';
|
||||
import Const from './const';
|
||||
import { getSelectionSummary } from './store/selection';
|
||||
|
||||
class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
constructor(props) {
|
||||
@@ -44,6 +43,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
data,
|
||||
columns,
|
||||
keyField,
|
||||
tabIndexCell,
|
||||
id,
|
||||
classes,
|
||||
striped,
|
||||
@@ -56,7 +56,9 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
rowClasses,
|
||||
wrapperClasses,
|
||||
rowEvents,
|
||||
selected
|
||||
selectRow,
|
||||
expandRow,
|
||||
cellEdit
|
||||
} = this.props;
|
||||
|
||||
const tableWrapperClass = cs('react-bootstrap-table', wrapperClasses);
|
||||
@@ -68,20 +70,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
'table-condensed': condensed
|
||||
}, classes);
|
||||
|
||||
const cellSelectionInfo = this.resolveSelectRowProps({
|
||||
onRowSelect: this.props.onRowSelect
|
||||
});
|
||||
|
||||
const { allRowsSelected, allRowsNotSelected } = getSelectionSummary(data, keyField, selected);
|
||||
const headerCellSelectionInfo = this.resolveSelectRowPropsForHeader({
|
||||
onAllRowsSelect: this.props.onAllRowsSelect,
|
||||
selected,
|
||||
allRowsSelected,
|
||||
allRowsNotSelected
|
||||
});
|
||||
|
||||
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
||||
const expandRow = this.resolveExpandRowProps();
|
||||
|
||||
return (
|
||||
<div className={ tableWrapperClass }>
|
||||
@@ -95,19 +84,19 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
onSort={ this.props.onSort }
|
||||
onFilter={ this.props.onFilter }
|
||||
onExternalFilter={ this.props.onExternalFilter }
|
||||
selectRow={ headerCellSelectionInfo }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
<Body
|
||||
data={ data }
|
||||
keyField={ keyField }
|
||||
tabIndexCell={ tabIndexCell }
|
||||
columns={ columns }
|
||||
isEmpty={ this.isEmpty() }
|
||||
visibleColumnSize={ this.visibleColumnSize() }
|
||||
noDataIndication={ noDataIndication }
|
||||
cellEdit={ this.props.cellEdit || {} }
|
||||
selectRow={ cellSelectionInfo }
|
||||
selectedRowKeys={ selected }
|
||||
cellEdit={ cellEdit }
|
||||
selectRow={ selectRow }
|
||||
expandRow={ expandRow }
|
||||
rowStyle={ rowStyle }
|
||||
rowClasses={ rowClasses }
|
||||
@@ -131,6 +120,7 @@ BootstrapTable.propTypes = {
|
||||
striped: PropTypes.bool,
|
||||
bordered: PropTypes.bool,
|
||||
hover: PropTypes.bool,
|
||||
tabIndexCell: PropTypes.bool,
|
||||
id: PropTypes.string,
|
||||
classes: PropTypes.string,
|
||||
wrapperClasses: PropTypes.string,
|
||||
@@ -143,9 +133,15 @@ BootstrapTable.propTypes = {
|
||||
filter: PropTypes.object,
|
||||
cellEdit: PropTypes.object,
|
||||
selectRow: PropTypes.shape({
|
||||
mode: PropTypes.oneOf([Const.ROW_SELECT_SINGLE, Const.ROW_SELECT_MULTIPLE]).isRequired,
|
||||
mode: PropTypes.oneOf([
|
||||
Const.ROW_SELECT_SINGLE,
|
||||
Const.ROW_SELECT_MULTIPLE,
|
||||
Const.ROW_SELECT_DISABLED
|
||||
]).isRequired,
|
||||
clickToSelect: PropTypes.bool,
|
||||
clickToExpand: PropTypes.bool,
|
||||
clickToEdit: PropTypes.bool,
|
||||
hideSelectAll: PropTypes.bool,
|
||||
onSelect: PropTypes.func,
|
||||
onSelectAll: PropTypes.func,
|
||||
style: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
@@ -156,21 +152,18 @@ BootstrapTable.propTypes = {
|
||||
selectionRenderer: PropTypes.func,
|
||||
selectionHeaderRenderer: PropTypes.func
|
||||
}),
|
||||
onRowSelect: PropTypes.func,
|
||||
onAllRowsSelect: PropTypes.func,
|
||||
expandRow: PropTypes.shape({
|
||||
renderer: PropTypes.func.isRequired,
|
||||
renderer: PropTypes.func,
|
||||
expanded: PropTypes.array,
|
||||
onExpand: PropTypes.func,
|
||||
onExpandAll: PropTypes.func,
|
||||
nonExpandable: PropTypes.array,
|
||||
showExpandColumn: PropTypes.bool,
|
||||
onlyOneExpanding: PropTypes.bool,
|
||||
expandByColumnOnly: PropTypes.bool,
|
||||
expandColumnRenderer: PropTypes.func,
|
||||
expandHeaderColumnRenderer: PropTypes.func
|
||||
}),
|
||||
onRowExpand: PropTypes.func,
|
||||
onAllRowExpand: PropTypes.func,
|
||||
isAnyExpands: PropTypes.bool,
|
||||
rowStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
rowEvents: PropTypes.object,
|
||||
rowClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
@@ -200,7 +193,21 @@ BootstrapTable.defaultProps = {
|
||||
bordered: true,
|
||||
hover: false,
|
||||
condensed: false,
|
||||
noDataIndication: null
|
||||
noDataIndication: null,
|
||||
selectRow: {
|
||||
mode: Const.ROW_SELECT_DISABLED,
|
||||
selected: [],
|
||||
hideSelectColumn: true
|
||||
},
|
||||
expandRow: {
|
||||
renderer: undefined,
|
||||
expanded: [],
|
||||
nonExpandable: []
|
||||
},
|
||||
cellEdit: {
|
||||
mode: null,
|
||||
nonEditableRows: []
|
||||
}
|
||||
};
|
||||
|
||||
export default BootstrapTable;
|
||||
|
||||
20
packages/react-bootstrap-table2/src/cell.js
vendored
20
packages/react-bootstrap-table2/src/cell.js
vendored
@@ -11,9 +11,18 @@ class Cell extends Component {
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const shouldUpdate =
|
||||
_.get(this.props.row, this.props.column.dataField)
|
||||
!== _.get(nextProps.row, nextProps.column.dataField) ||
|
||||
let shouldUpdate = false;
|
||||
if (nextProps.column.isDummyField) {
|
||||
shouldUpdate = !_.isEqual(this.props.row, nextProps.row);
|
||||
} else {
|
||||
shouldUpdate =
|
||||
_.get(this.props.row, this.props.column.dataField)
|
||||
!== _.get(nextProps.row, nextProps.column.dataField);
|
||||
}
|
||||
|
||||
if (shouldUpdate) return true;
|
||||
|
||||
shouldUpdate =
|
||||
this.props.column.hidden !== nextProps.column.hidden ||
|
||||
this.props.rowIndex !== nextProps.rowIndex ||
|
||||
this.props.columnIndex !== nextProps.columnIndex ||
|
||||
@@ -25,7 +34,8 @@ class Cell extends Component {
|
||||
!_.isEqual(this.props.style, nextProps.style) ||
|
||||
!_.isEqual(this.props.column.formatExtraData, nextProps.column.formatExtraData) ||
|
||||
!_.isEqual(this.props.column.events, nextProps.column.events) ||
|
||||
!_.isEqual(this.props.column.attrs, nextProps.column.attrs);
|
||||
!_.isEqual(this.props.column.attrs, nextProps.column.attrs) ||
|
||||
this.props.tabIndex !== nextProps.tabIndex;
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
@@ -64,7 +74,7 @@ class Cell extends Component {
|
||||
formatExtraData
|
||||
} = column;
|
||||
const attrs = { ...rest };
|
||||
let content = _.get(row, dataField);
|
||||
let content = column.isDummyField ? null : _.get(row, dataField);
|
||||
|
||||
if (formatter) {
|
||||
content = column.formatter(content, row, rowIndex, formatExtraData);
|
||||
|
||||
@@ -4,8 +4,8 @@ import React, { Component } from 'react';
|
||||
import _ from '../utils';
|
||||
import createDataContext from './data-context';
|
||||
import createSortContext from './sort-context';
|
||||
import createSelectionContext from './selection-context';
|
||||
import createRowExpandContext from './row-expand-context';
|
||||
import SelectionContext from './selection-context';
|
||||
import RowExpandContext from './row-expand-context';
|
||||
import remoteResolver from '../props-resolver/remote-resolver';
|
||||
import { BootstrapContext } from './bootstrap';
|
||||
import dataOperator from '../store/operators';
|
||||
@@ -22,11 +22,11 @@ const withContext = Base =>
|
||||
}
|
||||
|
||||
if (props.selectRow) {
|
||||
this.SelectionContext = createSelectionContext(dataOperator);
|
||||
this.SelectionContext = SelectionContext;
|
||||
}
|
||||
|
||||
if (props.expandRow) {
|
||||
this.RowExpandContext = createRowExpandContext(dataOperator);
|
||||
this.RowExpandContext = RowExpandContext;
|
||||
}
|
||||
|
||||
if (props.cellEdit && props.cellEdit.createContext) {
|
||||
@@ -54,26 +54,31 @@ const withContext = Base =>
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!nextProps.pagination && this.props.pagination) {
|
||||
this.PaginationContext = null;
|
||||
}
|
||||
if (nextProps.pagination && !this.props.pagination) {
|
||||
this.PaginationContext = nextProps.pagination.createContext(
|
||||
this.isRemotePagination, this.handleRemotePageChange);
|
||||
}
|
||||
}
|
||||
|
||||
renderBase() {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
paginationProps,
|
||||
expandProps,
|
||||
selectionProps
|
||||
) => (
|
||||
<Base
|
||||
ref={ n => this.table = n }
|
||||
{ ...this.props }
|
||||
{ ...selectionProps }
|
||||
{ ...sortProps }
|
||||
{ ...cellEditProps }
|
||||
{ ...filterProps }
|
||||
{ ...searchProps }
|
||||
{ ...paginationProps }
|
||||
{ ...expandProps }
|
||||
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
||||
/>
|
||||
);
|
||||
@@ -82,32 +87,26 @@ const withContext = Base =>
|
||||
renderWithSelectionCtx(base, baseProps) {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
paginationProps,
|
||||
expandProps
|
||||
paginationProps
|
||||
) => (
|
||||
<this.SelectionContext.Provider
|
||||
{ ...baseProps }
|
||||
ref={ n => this.selectionContext = n }
|
||||
selectRow={ this.props.selectRow }
|
||||
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
||||
>
|
||||
<this.SelectionContext.Consumer>
|
||||
{
|
||||
selectionProps => base(
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
paginationProps,
|
||||
expandProps,
|
||||
selectionProps
|
||||
)
|
||||
}
|
||||
</this.SelectionContext.Consumer>
|
||||
{
|
||||
base(
|
||||
rootProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
paginationProps
|
||||
)
|
||||
}
|
||||
</this.SelectionContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -115,7 +114,6 @@ const withContext = Base =>
|
||||
renderWithRowExpandCtx(base, baseProps) {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
@@ -123,22 +121,19 @@ const withContext = Base =>
|
||||
) => (
|
||||
<this.RowExpandContext.Provider
|
||||
{ ...baseProps }
|
||||
ref={ n => this.rowExpandContext = n }
|
||||
expandRow={ this.props.expandRow }
|
||||
data={ rootProps.getData(filterProps, searchProps, sortProps, paginationProps) }
|
||||
>
|
||||
<this.RowExpandContext.Consumer>
|
||||
{
|
||||
expandProps => base(
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
paginationProps,
|
||||
expandProps
|
||||
)
|
||||
}
|
||||
</this.RowExpandContext.Consumer>
|
||||
{
|
||||
base(
|
||||
rootProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
paginationProps
|
||||
)
|
||||
}
|
||||
</this.RowExpandContext.Provider>
|
||||
);
|
||||
}
|
||||
@@ -146,7 +141,6 @@ const withContext = Base =>
|
||||
renderWithPaginationCtx(base) {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps
|
||||
@@ -161,7 +155,6 @@ const withContext = Base =>
|
||||
{
|
||||
paginationProps => base(
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
@@ -176,7 +169,6 @@ const withContext = Base =>
|
||||
renderWithSortCtx(base, baseProps) {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps
|
||||
) => (
|
||||
@@ -191,7 +183,6 @@ const withContext = Base =>
|
||||
{
|
||||
sortProps => base(
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps,
|
||||
sortProps,
|
||||
@@ -205,7 +196,6 @@ const withContext = Base =>
|
||||
renderWithSearchCtx(base, baseProps) {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps
|
||||
) => (
|
||||
<this.SearchContext.Provider
|
||||
@@ -218,7 +208,6 @@ const withContext = Base =>
|
||||
{
|
||||
searchProps => base(
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps,
|
||||
searchProps
|
||||
)
|
||||
@@ -229,10 +218,7 @@ const withContext = Base =>
|
||||
}
|
||||
|
||||
renderWithFilterCtx(base, baseProps) {
|
||||
return (
|
||||
rootProps,
|
||||
cellEditProps
|
||||
) => (
|
||||
return rootProps => (
|
||||
<this.FilterContext.Provider
|
||||
{ ...baseProps }
|
||||
ref={ n => this.filterContext = n }
|
||||
@@ -242,7 +228,6 @@ const withContext = Base =>
|
||||
{
|
||||
filterProps => base(
|
||||
rootProps,
|
||||
cellEditProps,
|
||||
filterProps
|
||||
)
|
||||
}
|
||||
@@ -259,18 +244,15 @@ const withContext = Base =>
|
||||
cellEdit={ this.props.cellEdit }
|
||||
data={ rootProps.getData() }
|
||||
>
|
||||
<this.CellEditContext.Consumer>
|
||||
{
|
||||
cellEditProps => base(rootProps, cellEditProps)
|
||||
}
|
||||
</this.CellEditContext.Consumer>
|
||||
{ base(rootProps) }
|
||||
</this.CellEditContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { keyField, columns, bootstrap4 } = this.props;
|
||||
const { keyField, columns, bootstrap4, registerExposedAPI } = this.props;
|
||||
const baseProps = { keyField, columns };
|
||||
if (registerExposedAPI) baseProps.registerExposedAPI = registerExposedAPI;
|
||||
|
||||
let base = this.renderBase();
|
||||
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import dataOperator from '../store/operators';
|
||||
|
||||
export default (
|
||||
dataOperator
|
||||
) => {
|
||||
const RowExpandContext = React.createContext();
|
||||
const RowExpandContext = React.createContext();
|
||||
|
||||
class RowExpandProvider extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
keyField: PropTypes.string.isRequired
|
||||
}
|
||||
class RowExpandProvider extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
keyField: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
state = { expanded: this.props.expandRow.expanded || [] };
|
||||
state = { expanded: this.props.expandRow.expanded || [] };
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.expandRow) {
|
||||
this.setState(() => ({
|
||||
expanded: nextProps.expandRow.expanded || this.state.expanded
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
handleRowExpand = (rowKey, expanded, rowIndex, e) => {
|
||||
const { data, keyField, expandRow: { onExpand } } = this.props;
|
||||
|
||||
let currExpanded = [...this.state.expanded];
|
||||
|
||||
if (expanded) {
|
||||
currExpanded.push(rowKey);
|
||||
} else {
|
||||
currExpanded = currExpanded.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
if (onExpand) {
|
||||
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||
onExpand(row, expanded, rowIndex, e);
|
||||
}
|
||||
this.setState(() => ({ expanded: currExpanded }));
|
||||
}
|
||||
|
||||
handleAllRowExpand = (e, expandAll) => {
|
||||
const {
|
||||
data,
|
||||
keyField,
|
||||
expandRow: {
|
||||
onExpandAll,
|
||||
nonExpandable
|
||||
}
|
||||
} = this.props;
|
||||
const { expanded } = this.state;
|
||||
|
||||
let currExpanded;
|
||||
|
||||
if (expandAll) {
|
||||
currExpanded = expanded.concat(dataOperator.expandableKeys(data, keyField, nonExpandable));
|
||||
} else {
|
||||
currExpanded = expanded.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
|
||||
}
|
||||
|
||||
if (onExpandAll) {
|
||||
onExpandAll(expandAll, dataOperator.getExpandedRows(data, keyField, currExpanded), e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ expanded: currExpanded }));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, keyField } = this.props;
|
||||
return (
|
||||
<RowExpandContext.Provider
|
||||
value={ {
|
||||
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
|
||||
expanded: this.state.expanded,
|
||||
onRowExpand: this.handleRowExpand,
|
||||
onAllRowExpand: this.handleAllRowExpand
|
||||
} }
|
||||
>
|
||||
{ this.props.children }
|
||||
</RowExpandContext.Provider>
|
||||
);
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.expandRow) {
|
||||
this.setState(() => ({
|
||||
expanded: nextProps.expandRow.expanded || this.state.expanded
|
||||
}));
|
||||
}
|
||||
}
|
||||
return {
|
||||
Provider: RowExpandProvider,
|
||||
Consumer: RowExpandContext.Consumer
|
||||
};
|
||||
|
||||
handleRowExpand = (rowKey, expanded, rowIndex, e) => {
|
||||
const { data, keyField, expandRow: { onExpand, onlyOneExpanding } } = this.props;
|
||||
|
||||
let currExpanded = [...this.state.expanded];
|
||||
|
||||
if (expanded) {
|
||||
if (onlyOneExpanding) currExpanded = [rowKey];
|
||||
else currExpanded.push(rowKey);
|
||||
} else {
|
||||
currExpanded = currExpanded.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
if (onExpand) {
|
||||
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||
onExpand(row, expanded, rowIndex, e);
|
||||
}
|
||||
this.setState(() => ({ expanded: currExpanded }));
|
||||
}
|
||||
|
||||
handleAllRowExpand = (e, expandAll) => {
|
||||
const {
|
||||
data,
|
||||
keyField,
|
||||
expandRow: {
|
||||
onExpandAll,
|
||||
nonExpandable
|
||||
}
|
||||
} = this.props;
|
||||
const { expanded } = this.state;
|
||||
|
||||
let currExpanded;
|
||||
|
||||
if (expandAll) {
|
||||
currExpanded = expanded.concat(dataOperator.expandableKeys(data, keyField, nonExpandable));
|
||||
} else {
|
||||
currExpanded = expanded.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
|
||||
}
|
||||
|
||||
if (onExpandAll) {
|
||||
onExpandAll(expandAll, dataOperator.getExpandedRows(data, keyField, currExpanded), e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ expanded: currExpanded }));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, keyField } = this.props;
|
||||
return (
|
||||
<RowExpandContext.Provider
|
||||
value={ {
|
||||
...this.props.expandRow,
|
||||
expanded: this.state.expanded,
|
||||
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
|
||||
onRowExpand: this.handleRowExpand,
|
||||
onAllRowExpand: this.handleAllRowExpand
|
||||
} }
|
||||
>
|
||||
{ this.props.children }
|
||||
</RowExpandContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
Provider: RowExpandProvider,
|
||||
Consumer: RowExpandContext.Consumer
|
||||
};
|
||||
|
||||
@@ -3,92 +3,132 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Const from '../const';
|
||||
|
||||
export default (
|
||||
dataOperator
|
||||
) => {
|
||||
const SelectionContext = React.createContext();
|
||||
import dataOperator from '../store/operators';
|
||||
import { getSelectionSummary } from '../store/selection';
|
||||
|
||||
class SelectionProvider extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
keyField: PropTypes.string.isRequired
|
||||
}
|
||||
const SelectionContext = React.createContext();
|
||||
class SelectionProvider extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
keyField: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
state = { selected: (this.props.selectRow && this.props.selectRow.selected) || [] };
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.selectRow) {
|
||||
this.setState(() => ({
|
||||
selected: nextProps.selectRow.selected || this.state.selected
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
handleRowSelect = (rowKey, checked, rowIndex, e) => {
|
||||
const { data, keyField, selectRow: { mode, onSelect } } = this.props;
|
||||
const { ROW_SELECT_SINGLE } = Const;
|
||||
|
||||
let currSelected = [...this.state.selected];
|
||||
|
||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||
currSelected = [rowKey];
|
||||
} else if (checked) { // when select mode is checkbox
|
||||
currSelected.push(rowKey);
|
||||
} else {
|
||||
currSelected = currSelected.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
if (onSelect) {
|
||||
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||
onSelect(row, checked, rowIndex, e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ selected: currSelected }));
|
||||
}
|
||||
|
||||
handleAllRowsSelect = (e, isUnSelect) => {
|
||||
const {
|
||||
data,
|
||||
keyField,
|
||||
selectRow: {
|
||||
onSelectAll,
|
||||
nonSelectable
|
||||
}
|
||||
} = this.props;
|
||||
const { selected } = this.state;
|
||||
|
||||
let currSelected;
|
||||
|
||||
if (!isUnSelect) {
|
||||
currSelected = selected.concat(dataOperator.selectableKeys(data, keyField, nonSelectable));
|
||||
} else {
|
||||
currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
|
||||
}
|
||||
|
||||
if (onSelectAll) {
|
||||
onSelectAll(!isUnSelect, dataOperator.getSelectedRows(data, keyField, currSelected), e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ selected: currSelected }));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SelectionContext.Provider
|
||||
value={ {
|
||||
selected: this.state.selected,
|
||||
onRowSelect: this.handleRowSelect,
|
||||
onAllRowsSelect: this.handleAllRowsSelect
|
||||
} }
|
||||
>
|
||||
{ this.props.children }
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
if (props.registerExposedAPI) {
|
||||
const getSelected = () => this.getSelected();
|
||||
props.registerExposedAPI(getSelected);
|
||||
}
|
||||
}
|
||||
return {
|
||||
Provider: SelectionProvider,
|
||||
Consumer: SelectionContext.Consumer
|
||||
};
|
||||
|
||||
state = { selected: this.props.selectRow.selected || [] };
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.selectRow) {
|
||||
this.setState(() => ({
|
||||
selected: nextProps.selectRow.selected || this.state.selected
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// exposed API
|
||||
getSelected() {
|
||||
return this.state.selected;
|
||||
}
|
||||
|
||||
handleRowSelect = (rowKey, checked, rowIndex, e) => {
|
||||
const { data, keyField, selectRow: { mode, onSelect } } = this.props;
|
||||
const { ROW_SELECT_SINGLE } = Const;
|
||||
|
||||
let currSelected = [...this.state.selected];
|
||||
|
||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||
currSelected = [rowKey];
|
||||
} else if (checked) { // when select mode is checkbox
|
||||
currSelected.push(rowKey);
|
||||
} else {
|
||||
currSelected = currSelected.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
if (onSelect) {
|
||||
const row = dataOperator.getRowByRowId(data, keyField, rowKey);
|
||||
onSelect(row, checked, rowIndex, e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ selected: currSelected }));
|
||||
}
|
||||
|
||||
handleAllRowsSelect = (e, isUnSelect) => {
|
||||
const {
|
||||
data,
|
||||
keyField,
|
||||
selectRow: {
|
||||
onSelectAll,
|
||||
nonSelectable
|
||||
}
|
||||
} = this.props;
|
||||
const { selected } = this.state;
|
||||
|
||||
let currSelected;
|
||||
|
||||
if (!isUnSelect) {
|
||||
currSelected = selected.concat(dataOperator.selectableKeys(data, keyField, nonSelectable));
|
||||
} else {
|
||||
currSelected = selected.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined');
|
||||
}
|
||||
|
||||
if (onSelectAll) {
|
||||
onSelectAll(
|
||||
!isUnSelect,
|
||||
dataOperator.getSelectedRows(
|
||||
data,
|
||||
keyField,
|
||||
isUnSelect ? this.state.selected : currSelected
|
||||
),
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
this.setState(() => ({ selected: currSelected }));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
allRowsSelected,
|
||||
allRowsNotSelected
|
||||
} = getSelectionSummary(
|
||||
this.props.data,
|
||||
this.props.keyField,
|
||||
this.state.selected
|
||||
);
|
||||
|
||||
let checkedStatus;
|
||||
|
||||
// checkbox status depending on selected rows counts
|
||||
if (allRowsSelected) checkedStatus = Const.CHECKBOX_STATUS_CHECKED;
|
||||
else if (allRowsNotSelected) checkedStatus = Const.CHECKBOX_STATUS_UNCHECKED;
|
||||
else checkedStatus = Const.CHECKBOX_STATUS_INDETERMINATE;
|
||||
|
||||
return (
|
||||
<SelectionContext.Provider
|
||||
value={ {
|
||||
...this.props.selectRow,
|
||||
selected: this.state.selected,
|
||||
onRowSelect: this.handleRowSelect,
|
||||
onAllRowsSelect: this.handleAllRowsSelect,
|
||||
allRowsSelected,
|
||||
allRowsNotSelected,
|
||||
checkedStatus
|
||||
} }
|
||||
>
|
||||
{ this.props.children }
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
Provider: SelectionProvider,
|
||||
Consumer: SelectionContext.Consumer
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@ const HeaderCell = (props) => {
|
||||
const {
|
||||
text,
|
||||
sort,
|
||||
sortCaret,
|
||||
filter,
|
||||
filterRenderer,
|
||||
headerTitle,
|
||||
@@ -49,6 +50,7 @@ const HeaderCell = (props) => {
|
||||
|
||||
if (headerStyle) {
|
||||
cellStyle = _.isFunction(headerStyle) ? headerStyle(column, index) : headerStyle;
|
||||
cellStyle = cellStyle ? { ...cellStyle } : cellStyle;
|
||||
}
|
||||
|
||||
if (headerTitle) {
|
||||
@@ -68,7 +70,7 @@ const HeaderCell = (props) => {
|
||||
cellAttrs.className = cs(cellAttrs.className, 'sortable');
|
||||
|
||||
if (sorting) {
|
||||
sortSymbol = <SortCaret order={ sortOrder } />;
|
||||
sortSymbol = sortCaret ? sortCaret(sortOrder, column) : <SortCaret order={ sortOrder } />;
|
||||
|
||||
// append customized classes or style if table was sorting based on the current column.
|
||||
cellClasses = cs(
|
||||
@@ -85,7 +87,7 @@ const HeaderCell = (props) => {
|
||||
: headerSortingStyle
|
||||
};
|
||||
} else {
|
||||
sortSymbol = <SortSymbol />;
|
||||
sortSymbol = sortCaret ? sortCaret(undefined, column) : <SortSymbol />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +116,7 @@ HeaderCell.propTypes = {
|
||||
column: PropTypes.shape({
|
||||
dataField: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
isDummyField: PropTypes.bool,
|
||||
hidden: PropTypes.bool,
|
||||
headerFormatter: PropTypes.func,
|
||||
formatter: PropTypes.func,
|
||||
@@ -149,6 +152,7 @@ HeaderCell.propTypes = {
|
||||
onSort: PropTypes.func,
|
||||
sorting: PropTypes.bool,
|
||||
sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]),
|
||||
sortCaret: PropTypes.func,
|
||||
isLastSorting: PropTypes.bool,
|
||||
onFilter: PropTypes.func,
|
||||
onExternalFilter: PropTypes.func
|
||||
|
||||
29
packages/react-bootstrap-table2/src/header.js
vendored
29
packages/react-bootstrap-table2/src/header.js
vendored
@@ -1,15 +1,14 @@
|
||||
/* eslint react/require-default-props: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Const from './const';
|
||||
|
||||
import HeaderCell from './header-cell';
|
||||
import SelectionHeaderCell from './row-selection/selection-header-cell';
|
||||
import ExpandHeaderCell from './row-expand/expand-header-cell';
|
||||
import withHeaderSelection from './row-selection/selection-header-cell-consumer';
|
||||
import withHeaderExpansion from './row-expand/expand-header-cell-consumer';
|
||||
|
||||
const Header = (props) => {
|
||||
const { ROW_SELECT_DISABLED } = Const;
|
||||
|
||||
const {
|
||||
className,
|
||||
columns,
|
||||
@@ -23,20 +22,24 @@ const Header = (props) => {
|
||||
bootstrap4
|
||||
} = props;
|
||||
|
||||
let SelectionHeaderCellComp = () => null;
|
||||
let ExpansionHeaderCellComp = () => null;
|
||||
|
||||
if (expandRow.showExpandColumn) {
|
||||
ExpansionHeaderCellComp = withHeaderExpansion(ExpandHeaderCell);
|
||||
}
|
||||
|
||||
if (selectRow) {
|
||||
SelectionHeaderCellComp = withHeaderSelection(SelectionHeaderCell);
|
||||
}
|
||||
|
||||
return (
|
||||
<thead>
|
||||
<tr className={ className }>
|
||||
<ExpansionHeaderCellComp />
|
||||
{
|
||||
(expandRow && expandRow.showExpandColumn)
|
||||
? <ExpandHeaderCell
|
||||
onAllRowExpand={ expandRow.onAllRowExpand }
|
||||
anyExpands={ expandRow.isAnyExpands }
|
||||
renderer={ expandRow.expandHeaderColumnRenderer }
|
||||
/> : null
|
||||
}
|
||||
{
|
||||
(selectRow.mode !== ROW_SELECT_DISABLED && !selectRow.hideSelectColumn)
|
||||
? <SelectionHeaderCell { ...selectRow } /> : null
|
||||
!selectRow.hideSelectColumn ?
|
||||
<SelectionHeaderCellComp /> : null
|
||||
}
|
||||
{
|
||||
columns.map((column, i) => {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
export default ExtendBase =>
|
||||
class ExpandRowResolver extends ExtendBase {
|
||||
resolveExpandRowProps() {
|
||||
const { expandRow, expanded, onRowExpand, onAllRowExpand, isAnyExpands } = this.props;
|
||||
if (expandRow) {
|
||||
return {
|
||||
...expandRow,
|
||||
expanded,
|
||||
onRowExpand,
|
||||
onAllRowExpand,
|
||||
isAnyExpands,
|
||||
nonExpandable: expandRow.nonExpandable || []
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -1,11 +1,7 @@
|
||||
import ColumnResolver from './column-resolver';
|
||||
import ExpandRowResolver from './expand-row-resolver';
|
||||
import Const from '../const';
|
||||
import _ from '../utils';
|
||||
|
||||
export default ExtendBase =>
|
||||
class TableResolver extends
|
||||
ExpandRowResolver(ColumnResolver(ExtendBase)) {
|
||||
class TableResolver extends ColumnResolver(ExtendBase) {
|
||||
validateProps() {
|
||||
const { keyField } = this.props;
|
||||
if (!keyField) {
|
||||
@@ -19,63 +15,4 @@ export default ExtendBase =>
|
||||
isEmpty() {
|
||||
return this.props.data.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* props resolver for cell selection
|
||||
* @param {Object} options - addtional options like callback which are about to merge into props
|
||||
*
|
||||
* @returns {Object} result - props for cell selections
|
||||
* @returns {String} result.mode - input type of row selection or disabled.
|
||||
*/
|
||||
resolveSelectRowProps(options) {
|
||||
const { selectRow } = this.props;
|
||||
const { ROW_SELECT_DISABLED } = Const;
|
||||
|
||||
if (_.isDefined(selectRow)) {
|
||||
return {
|
||||
...selectRow,
|
||||
...options
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
mode: ROW_SELECT_DISABLED
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* props resolver for header cell selection
|
||||
* @param {Object} options - addtional options like callback which are about to merge into props
|
||||
*
|
||||
* @returns {Object} result - props for cell selections
|
||||
* @returns {String} result.mode - input type of row selection or disabled.
|
||||
* @returns {String} result.checkedStatus - checkbox status depending on selected rows counts
|
||||
*/
|
||||
resolveSelectRowPropsForHeader(options = {}) {
|
||||
const { selectRow } = this.props;
|
||||
const { allRowsSelected, allRowsNotSelected, ...rest } = options;
|
||||
const {
|
||||
ROW_SELECT_DISABLED, CHECKBOX_STATUS_CHECKED,
|
||||
CHECKBOX_STATUS_INDETERMINATE, CHECKBOX_STATUS_UNCHECKED
|
||||
} = Const;
|
||||
|
||||
if (_.isDefined(selectRow)) {
|
||||
let checkedStatus;
|
||||
|
||||
// checkbox status depending on selected rows counts
|
||||
if (allRowsSelected) checkedStatus = CHECKBOX_STATUS_CHECKED;
|
||||
else if (allRowsNotSelected) checkedStatus = CHECKBOX_STATUS_UNCHECKED;
|
||||
else checkedStatus = CHECKBOX_STATUS_INDETERMINATE;
|
||||
|
||||
return {
|
||||
...selectRow,
|
||||
...rest,
|
||||
checkedStatus
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
mode: ROW_SELECT_DISABLED
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import _ from './utils';
|
||||
import Const from './const';
|
||||
|
||||
const events = [
|
||||
'onClick',
|
||||
'onDoubleClick',
|
||||
'onMouseEnter',
|
||||
'onMouseLeave'
|
||||
'onMouseLeave',
|
||||
'onContextMenu'
|
||||
];
|
||||
|
||||
export default ExtendBase =>
|
||||
@@ -14,7 +12,6 @@ export default ExtendBase =>
|
||||
super(props);
|
||||
this.clickNum = 0;
|
||||
this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this);
|
||||
this.createClickEventHandler = this.createClickEventHandler.bind(this);
|
||||
}
|
||||
|
||||
createDefaultEventHandler(cb) {
|
||||
@@ -24,65 +21,11 @@ export default ExtendBase =>
|
||||
};
|
||||
}
|
||||
|
||||
createClickEventHandler(cb) {
|
||||
return (e) => {
|
||||
const {
|
||||
row,
|
||||
selected,
|
||||
keyField,
|
||||
selectable,
|
||||
expandable,
|
||||
rowIndex,
|
||||
expanded,
|
||||
expandRow,
|
||||
selectRow,
|
||||
cellEdit: {
|
||||
mode,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
DELAY_FOR_DBCLICK
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
const clickFn = () => {
|
||||
if (cb) {
|
||||
cb(e, row, rowIndex);
|
||||
}
|
||||
const key = _.get(row, keyField);
|
||||
if (expandRow && expandable) {
|
||||
expandRow.onRowExpand(key, !expanded, rowIndex, e);
|
||||
}
|
||||
if (selectRow.mode !== Const.ROW_SELECT_DISABLED && selectable) {
|
||||
selectRow.onRowSelect(key, !selected, rowIndex, e);
|
||||
}
|
||||
};
|
||||
|
||||
if (mode === DBCLICK_TO_CELL_EDIT && selectRow.clickToEdit) {
|
||||
this.clickNum += 1;
|
||||
_.debounce(() => {
|
||||
if (this.clickNum === 1) {
|
||||
clickFn();
|
||||
}
|
||||
this.clickNum = 0;
|
||||
}, DELAY_FOR_DBCLICK)();
|
||||
} else {
|
||||
clickFn();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
delegate(attrs = {}) {
|
||||
const newAttrs = {};
|
||||
const { expandRow, selectRow } = this.props;
|
||||
if (expandRow || (selectRow && selectRow.clickToSelect)) {
|
||||
newAttrs.onClick = this.createClickEventHandler(attrs.onClick);
|
||||
}
|
||||
const newAttrs = { ...attrs };
|
||||
Object.keys(attrs).forEach((attr) => {
|
||||
if (!newAttrs[attr]) {
|
||||
if (events.includes(attr)) {
|
||||
newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]);
|
||||
} else {
|
||||
newAttrs[attr] = attrs[attr];
|
||||
}
|
||||
if (events.includes(attr)) {
|
||||
newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]);
|
||||
}
|
||||
});
|
||||
return newAttrs;
|
||||
|
||||
@@ -12,7 +12,8 @@ export default class ExpandCell extends Component {
|
||||
expanded: PropTypes.bool.isRequired,
|
||||
onRowExpand: PropTypes.func.isRequired,
|
||||
expandColumnRenderer: PropTypes.func,
|
||||
rowIndex: PropTypes.number
|
||||
rowIndex: PropTypes.number,
|
||||
tabIndex: PropTypes.number
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@@ -20,17 +21,29 @@ export default class ExpandCell extends Component {
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const shouldUpdate =
|
||||
this.props.rowIndex !== nextProps.rowIndex ||
|
||||
this.props.expanded !== nextProps.expanded ||
|
||||
this.props.rowKey !== nextProps.rowKey ||
|
||||
this.props.tabIndex !== nextProps.tabIndex;
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
const { rowKey, expanded, onRowExpand, rowIndex } = this.props;
|
||||
|
||||
onRowExpand(rowKey, expanded, rowIndex, e);
|
||||
onRowExpand(rowKey, !expanded, rowIndex, e);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { expanded, expandColumnRenderer } = this.props;
|
||||
const { expanded, expandColumnRenderer, tabIndex } = this.props;
|
||||
const attrs = {};
|
||||
if (tabIndex !== -1) attrs.tabIndex = tabIndex;
|
||||
|
||||
return (
|
||||
<td onClick={ this.handleClick }>
|
||||
<td onClick={ this.handleClick } { ...attrs }>
|
||||
{
|
||||
expandColumnRenderer ? expandColumnRenderer({
|
||||
expanded
|
||||
|
||||
8
packages/react-bootstrap-table2/src/row-expand/expand-header-cell-consumer.js
vendored
Normal file
8
packages/react-bootstrap-table2/src/row-expand/expand-header-cell-consumer.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import ExpansionContext from '../contexts/row-expand-context';
|
||||
|
||||
export default Component => () => (
|
||||
<ExpansionContext.Consumer>
|
||||
{ expandRow => <Component { ...expandRow } /> }
|
||||
</ExpansionContext.Consumer>
|
||||
);
|
||||
@@ -3,11 +3,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class SelectionHeaderCell extends Component {
|
||||
export default class ExpansionHeaderCell extends Component {
|
||||
static propTypes = {
|
||||
anyExpands: PropTypes.bool.isRequired,
|
||||
isAnyExpands: PropTypes.bool.isRequired,
|
||||
onAllRowExpand: PropTypes.func.isRequired,
|
||||
renderer: PropTypes.func
|
||||
expandHeaderColumnRenderer: PropTypes.func
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@@ -16,13 +16,13 @@ export default class SelectionHeaderCell extends Component {
|
||||
}
|
||||
|
||||
handleCheckBoxClick(e) {
|
||||
const { anyExpands, onAllRowExpand } = this.props;
|
||||
const { isAnyExpands, onAllRowExpand } = this.props;
|
||||
|
||||
onAllRowExpand(e, !anyExpands);
|
||||
onAllRowExpand(e, !isAnyExpands);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { anyExpands, renderer } = this.props;
|
||||
const { isAnyExpands, expandHeaderColumnRenderer } = this.props;
|
||||
const attrs = {
|
||||
onClick: this.handleCheckBoxClick
|
||||
};
|
||||
@@ -30,9 +30,9 @@ export default class SelectionHeaderCell extends Component {
|
||||
return (
|
||||
<th data-row-selection { ...attrs }>
|
||||
{
|
||||
renderer ?
|
||||
renderer({ isAnyExpands: anyExpands }) :
|
||||
(anyExpands ? '(-)' : '(+)')
|
||||
expandHeaderColumnRenderer ?
|
||||
expandHeaderColumnRenderer({ isAnyExpands }) :
|
||||
(isAnyExpands ? '(-)' : '(+)')
|
||||
}
|
||||
</th>
|
||||
);
|
||||
|
||||
34
packages/react-bootstrap-table2/src/row-expand/row-consumer.js
vendored
Normal file
34
packages/react-bootstrap-table2/src/row-expand/row-consumer.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import ExpandRow from './expand-row';
|
||||
import ExpansionContext from '../contexts/row-expand-context';
|
||||
|
||||
export default (Component, visibleColumnSize) => {
|
||||
const renderWithExpansion = (props, expandRow) => {
|
||||
const key = props.value;
|
||||
|
||||
const expanded = expandRow.expanded.includes(key);
|
||||
const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key);
|
||||
|
||||
return [
|
||||
<Component
|
||||
{ ...props }
|
||||
key={ key }
|
||||
expanded={ expanded }
|
||||
expandable={ expandable }
|
||||
expandRow={ { ...expandRow } }
|
||||
/>,
|
||||
expanded ? <ExpandRow
|
||||
key={ `${key}-expanding` }
|
||||
colSpan={ visibleColumnSize }
|
||||
>
|
||||
{ expandRow.renderer(props.row) }
|
||||
</ExpandRow> : null
|
||||
];
|
||||
};
|
||||
return props => (
|
||||
<ExpansionContext.Consumer>
|
||||
{ expandRow => renderWithExpansion(props, expandRow) }
|
||||
</ExpansionContext.Consumer>
|
||||
);
|
||||
};
|
||||
63
packages/react-bootstrap-table2/src/row-selection/row-consumer.js
vendored
Normal file
63
packages/react-bootstrap-table2/src/row-selection/row-consumer.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import cs from 'classnames';
|
||||
import _ from '../utils';
|
||||
import SelectionContext from '../contexts/selection-context';
|
||||
|
||||
export default (Component) => {
|
||||
const renderWithSelection = (props, selectRow) => {
|
||||
const key = props.value;
|
||||
const selected = selectRow.selected.includes(key);
|
||||
const selectable = !selectRow.nonSelectable || !selectRow.nonSelectable.includes(key);
|
||||
|
||||
let {
|
||||
style,
|
||||
className
|
||||
} = props;
|
||||
|
||||
if (selected) {
|
||||
const selectedStyle = _.isFunction(selectRow.style)
|
||||
? selectRow.style(props.row, props.rowIndex)
|
||||
: selectRow.style;
|
||||
|
||||
const selectedClasses = _.isFunction(selectRow.classes)
|
||||
? selectRow.classes(props.row, props.rowIndex)
|
||||
: selectRow.classes;
|
||||
|
||||
style = {
|
||||
...style,
|
||||
...selectedStyle
|
||||
};
|
||||
className = cs(className, selectedClasses) || undefined;
|
||||
|
||||
if (selectRow.bgColor) {
|
||||
style = style || {};
|
||||
style.backgroundColor = _.isFunction(selectRow.bgColor)
|
||||
? selectRow.bgColor(props.row, props.rowIndex)
|
||||
: selectRow.bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Component
|
||||
{ ...props }
|
||||
style={ style }
|
||||
className={ className }
|
||||
selectRow={ selectRow }
|
||||
selected={ selected }
|
||||
selectable={ selectable }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
function withConsumer(props) {
|
||||
return (
|
||||
<SelectionContext.Consumer>
|
||||
{ selectRow => renderWithSelection(props, selectRow) }
|
||||
</SelectionContext.Consumer>
|
||||
);
|
||||
}
|
||||
|
||||
withConsumer.displayName = 'WithSelectionRowConsumer';
|
||||
return withConsumer;
|
||||
};
|
||||
@@ -15,6 +15,7 @@ export default class SelectionCell extends Component {
|
||||
onRowSelect: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
rowIndex: PropTypes.number,
|
||||
tabIndex: PropTypes.number,
|
||||
clickToSelect: PropTypes.bool,
|
||||
selectionRenderer: PropTypes.func
|
||||
}
|
||||
@@ -25,9 +26,14 @@ export default class SelectionCell extends Component {
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const { selected } = this.props;
|
||||
const shouldUpdate =
|
||||
this.props.rowIndex !== nextProps.rowIndex ||
|
||||
this.props.selected !== nextProps.selected ||
|
||||
this.props.disabled !== nextProps.disabled ||
|
||||
this.props.rowKey !== nextProps.rowKey ||
|
||||
this.props.tabIndex !== nextProps.tabIndex;
|
||||
|
||||
return nextProps.selected !== selected;
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
@@ -56,14 +62,18 @@ export default class SelectionCell extends Component {
|
||||
mode: inputType,
|
||||
selected,
|
||||
disabled,
|
||||
tabIndex,
|
||||
selectionRenderer
|
||||
} = this.props;
|
||||
|
||||
const attrs = {};
|
||||
if (tabIndex !== -1) attrs.tabIndex = tabIndex;
|
||||
|
||||
return (
|
||||
<BootstrapContext.Consumer>
|
||||
{
|
||||
({ bootstrap4 }) => (
|
||||
<td onClick={ this.handleClick }>
|
||||
<td onClick={ this.handleClick } { ...attrs }>
|
||||
{
|
||||
selectionRenderer ? selectionRenderer({
|
||||
mode: inputType,
|
||||
|
||||
8
packages/react-bootstrap-table2/src/row-selection/selection-header-cell-consumer.js
vendored
Normal file
8
packages/react-bootstrap-table2/src/row-selection/selection-header-cell-consumer.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import SelectionContext from '../contexts/selection-context';
|
||||
|
||||
export default Component => () => (
|
||||
<SelectionContext.Consumer>
|
||||
{ selectRow => <Component { ...selectRow } /> }
|
||||
</SelectionContext.Consumer>
|
||||
);
|
||||
@@ -27,6 +27,7 @@ export default class SelectionHeaderCell extends Component {
|
||||
mode: PropTypes.string.isRequired,
|
||||
checkedStatus: PropTypes.string,
|
||||
onAllRowsSelect: PropTypes.func,
|
||||
hideSelectAll: PropTypes.bool,
|
||||
selectionHeaderRenderer: PropTypes.func
|
||||
}
|
||||
|
||||
@@ -63,7 +64,10 @@ export default class SelectionHeaderCell extends Component {
|
||||
CHECKBOX_STATUS_CHECKED, CHECKBOX_STATUS_INDETERMINATE, ROW_SELECT_MULTIPLE
|
||||
} = Const;
|
||||
|
||||
const { mode, checkedStatus, selectionHeaderRenderer } = this.props;
|
||||
const { mode, checkedStatus, selectionHeaderRenderer, hideSelectAll } = this.props;
|
||||
if (hideSelectAll) {
|
||||
return <th data-row-selection />;
|
||||
}
|
||||
|
||||
const checked = checkedStatus === CHECKBOX_STATUS_CHECKED;
|
||||
|
||||
|
||||
183
packages/react-bootstrap-table2/src/row.js
vendored
183
packages/react-bootstrap-table2/src/row.js
vendored
@@ -1,183 +0,0 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/no-array-index-key: 0 */
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import _ from './utils';
|
||||
import Cell from './cell';
|
||||
import SelectionCell from './row-selection/selection-cell';
|
||||
import ExpandCell from './row-expand/expand-cell';
|
||||
import eventDelegater from './row-event-delegater';
|
||||
import Const from './const';
|
||||
|
||||
class Row extends eventDelegater(Component) {
|
||||
render() {
|
||||
const {
|
||||
row,
|
||||
columns,
|
||||
keyField,
|
||||
rowIndex,
|
||||
className,
|
||||
style,
|
||||
attrs,
|
||||
cellEdit,
|
||||
selected,
|
||||
selectRow,
|
||||
expanded,
|
||||
expandRow,
|
||||
selectable,
|
||||
editable: editableRow
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
mode,
|
||||
onStart,
|
||||
EditingCell,
|
||||
ridx: editingRowIdx,
|
||||
cidx: editingColIdx,
|
||||
CLICK_TO_CELL_EDIT,
|
||||
DBCLICK_TO_CELL_EDIT,
|
||||
...rest
|
||||
} = cellEdit;
|
||||
|
||||
const key = _.get(row, keyField);
|
||||
const { hideSelectColumn } = selectRow;
|
||||
const { showExpandColumn } = expandRow || {};
|
||||
const trAttrs = this.delegate(attrs);
|
||||
|
||||
return (
|
||||
<tr style={ style } className={ className } { ...trAttrs }>
|
||||
{
|
||||
showExpandColumn ? (
|
||||
<ExpandCell
|
||||
{ ...expandRow }
|
||||
rowKey={ key }
|
||||
rowIndex={ rowIndex }
|
||||
expanded={ expanded }
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
(selectRow.mode !== Const.ROW_SELECT_DISABLED && !hideSelectColumn)
|
||||
? (
|
||||
<SelectionCell
|
||||
{ ...selectRow }
|
||||
rowKey={ key }
|
||||
rowIndex={ rowIndex }
|
||||
selected={ selected }
|
||||
disabled={ !selectable }
|
||||
/>
|
||||
)
|
||||
: null
|
||||
}
|
||||
{
|
||||
columns.map((column, index) => {
|
||||
if (!column.hidden) {
|
||||
const { dataField } = column;
|
||||
const content = _.get(row, dataField);
|
||||
let editable = _.isDefined(column.editable) ? column.editable : true;
|
||||
if (dataField === keyField || !editableRow) editable = false;
|
||||
if (_.isFunction(column.editable)) {
|
||||
editable = column.editable(content, row, rowIndex, index);
|
||||
}
|
||||
if (rowIndex === editingRowIdx && index === editingColIdx) {
|
||||
let editCellstyle = column.editCellStyle || {};
|
||||
let editCellclasses = column.editCellClasses;
|
||||
if (_.isFunction(column.editCellStyle)) {
|
||||
editCellstyle = column.editCellStyle(content, row, rowIndex, index);
|
||||
}
|
||||
if (_.isFunction(column.editCellClasses)) {
|
||||
editCellclasses = column.editCellClasses(content, row, rowIndex, index);
|
||||
}
|
||||
return (
|
||||
<EditingCell
|
||||
key={ `${content}-${index}` }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
column={ column }
|
||||
columnIndex={ index }
|
||||
className={ editCellclasses }
|
||||
style={ editCellstyle }
|
||||
{ ...rest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
// render cell
|
||||
let cellTitle;
|
||||
let cellStyle = {};
|
||||
const cellAttrs = {
|
||||
..._.isFunction(column.attrs)
|
||||
? column.attrs(content, row, rowIndex, index)
|
||||
: column.attrs,
|
||||
...column.events
|
||||
};
|
||||
|
||||
const cellClasses = _.isFunction(column.classes)
|
||||
? column.classes(content, row, rowIndex, index)
|
||||
: column.classes;
|
||||
|
||||
if (column.style) {
|
||||
cellStyle = _.isFunction(column.style)
|
||||
? column.style(content, row, rowIndex, index)
|
||||
: column.style;
|
||||
cellStyle = Object.assign({}, cellStyle) || {};
|
||||
}
|
||||
|
||||
|
||||
if (column.title) {
|
||||
cellTitle = _.isFunction(column.title)
|
||||
? column.title(content, row, rowIndex, index)
|
||||
: content;
|
||||
cellAttrs.title = cellTitle;
|
||||
}
|
||||
|
||||
if (column.align) {
|
||||
cellStyle.textAlign =
|
||||
_.isFunction(column.align)
|
||||
? column.align(content, row, rowIndex, index)
|
||||
: column.align;
|
||||
}
|
||||
|
||||
if (cellClasses) cellAttrs.className = cellClasses;
|
||||
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||
|
||||
return (
|
||||
<Cell
|
||||
key={ `${content}-${index}` }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ index }
|
||||
column={ column }
|
||||
onStart={ onStart }
|
||||
editable={ editable }
|
||||
clickToEdit={ mode === CLICK_TO_CELL_EDIT }
|
||||
dbclickToEdit={ mode === DBCLICK_TO_CELL_EDIT }
|
||||
{ ...cellAttrs }
|
||||
/>
|
||||
);
|
||||
}
|
||||
return false;
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
row: PropTypes.object.isRequired,
|
||||
rowIndex: PropTypes.number.isRequired,
|
||||
columns: PropTypes.array.isRequired,
|
||||
style: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
attrs: PropTypes.object
|
||||
};
|
||||
|
||||
Row.defaultProps = {
|
||||
editable: true,
|
||||
style: {},
|
||||
className: null,
|
||||
attrs: {}
|
||||
};
|
||||
|
||||
export default Row;
|
||||
117
packages/react-bootstrap-table2/src/row/aggregate-row.js
vendored
Normal file
117
packages/react-bootstrap-table2/src/row/aggregate-row.js
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint no-plusplus: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import _ from '../utils';
|
||||
import ExpandCell from '../row-expand/expand-cell';
|
||||
import SelectionCell from '../row-selection/selection-cell';
|
||||
import shouldUpdater from './should-updater';
|
||||
import eventDelegater from './event-delegater';
|
||||
import RowPureContent from './row-pure-content';
|
||||
|
||||
export default class RowAggregator extends shouldUpdater(eventDelegater(React.Component)) {
|
||||
static propTypes = {
|
||||
attrs: PropTypes.object,
|
||||
style: PropTypes.object
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
attrs: {},
|
||||
style: {}
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.clickNum = 0;
|
||||
this.shouldUpdateRowContent = false;
|
||||
this.createClickEventHandler = this.createClickEventHandler.bind(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (
|
||||
this.props.selected !== nextProps.selected ||
|
||||
this.props.expanded !== nextProps.expanded ||
|
||||
this.props.selectable !== nextProps.selectable ||
|
||||
this.shouldUpdatedBySelfProps(nextProps)
|
||||
) {
|
||||
this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps);
|
||||
return true;
|
||||
}
|
||||
this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps);
|
||||
|
||||
return this.shouldUpdateRowContent;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
row,
|
||||
columns,
|
||||
keyField,
|
||||
rowIndex,
|
||||
style,
|
||||
className,
|
||||
attrs,
|
||||
selectRow,
|
||||
expandRow,
|
||||
expanded,
|
||||
selected,
|
||||
selectable,
|
||||
visibleColumnSize,
|
||||
tabIndexCell,
|
||||
...rest
|
||||
} = this.props;
|
||||
const key = _.get(row, keyField);
|
||||
const { hideSelectColumn, clickToSelect } = selectRow;
|
||||
const { showExpandColumn } = expandRow;
|
||||
|
||||
const newAttrs = this.delegate({ ...attrs });
|
||||
if (clickToSelect || !!expandRow.renderer) {
|
||||
newAttrs.onClick = this.createClickEventHandler(newAttrs.onClick);
|
||||
}
|
||||
|
||||
let tabIndexStart = (rowIndex * visibleColumnSize) + 1;
|
||||
|
||||
return (
|
||||
<tr
|
||||
style={ style }
|
||||
className={ className }
|
||||
{ ...newAttrs }
|
||||
>
|
||||
{
|
||||
showExpandColumn ? (
|
||||
<ExpandCell
|
||||
{ ...expandRow }
|
||||
rowKey={ key }
|
||||
rowIndex={ rowIndex }
|
||||
expanded={ expanded }
|
||||
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
!hideSelectColumn
|
||||
? (
|
||||
<SelectionCell
|
||||
{ ...selectRow }
|
||||
rowKey={ key }
|
||||
rowIndex={ rowIndex }
|
||||
selected={ selected }
|
||||
disabled={ !selectable }
|
||||
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
|
||||
/>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<RowPureContent
|
||||
row={ row }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
shouldUpdate={ this.shouldUpdateRowContent }
|
||||
tabIndexStart={ tabIndexCell ? tabIndexStart : -1 }
|
||||
{ ...rest }
|
||||
/>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
83
packages/react-bootstrap-table2/src/row/event-delegater.js
vendored
Normal file
83
packages/react-bootstrap-table2/src/row/event-delegater.js
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
import _ from '../utils';
|
||||
import Const from '../const';
|
||||
|
||||
const events = [
|
||||
'onClick',
|
||||
'onDoubleClick',
|
||||
'onMouseEnter',
|
||||
'onMouseLeave',
|
||||
'onContextMenu'
|
||||
];
|
||||
|
||||
export default ExtendBase =>
|
||||
class RowEventDelegater extends ExtendBase {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.clickNum = 0;
|
||||
this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this);
|
||||
this.createClickEventHandler = this.createClickEventHandler.bind(this);
|
||||
}
|
||||
|
||||
createClickEventHandler(cb) {
|
||||
return (e) => {
|
||||
const {
|
||||
row,
|
||||
selected,
|
||||
keyField,
|
||||
selectable,
|
||||
expandable,
|
||||
rowIndex,
|
||||
expanded,
|
||||
expandRow,
|
||||
selectRow,
|
||||
DELAY_FOR_DBCLICK
|
||||
} = this.props;
|
||||
const clickFn = () => {
|
||||
if (cb) {
|
||||
cb(e, row, rowIndex);
|
||||
}
|
||||
const key = _.get(row, keyField);
|
||||
if (expandRow && expandable && !expandRow.expandByColumnOnly) {
|
||||
if (
|
||||
(selectRow.mode !== Const.ROW_SELECT_DISABLED && selectRow.clickToExpand) ||
|
||||
selectRow.mode === Const.ROW_SELECT_DISABLED
|
||||
) {
|
||||
expandRow.onRowExpand(key, !expanded, rowIndex, e);
|
||||
}
|
||||
}
|
||||
if (selectRow.clickToSelect && selectable) {
|
||||
selectRow.onRowSelect(key, !selected, rowIndex, e);
|
||||
}
|
||||
};
|
||||
|
||||
if (DELAY_FOR_DBCLICK) {
|
||||
this.clickNum += 1;
|
||||
_.debounce(() => {
|
||||
if (this.clickNum === 1) {
|
||||
clickFn();
|
||||
}
|
||||
this.clickNum = 0;
|
||||
}, DELAY_FOR_DBCLICK)();
|
||||
} else {
|
||||
clickFn();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
createDefaultEventHandler(cb) {
|
||||
return (e) => {
|
||||
const { row, rowIndex } = this.props;
|
||||
cb(e, row, rowIndex);
|
||||
};
|
||||
}
|
||||
|
||||
delegate(attrs = {}) {
|
||||
const newAttrs = { ...attrs };
|
||||
Object.keys(attrs).forEach((attr) => {
|
||||
if (events.includes(attr)) {
|
||||
newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]);
|
||||
}
|
||||
});
|
||||
return newAttrs;
|
||||
}
|
||||
};
|
||||
116
packages/react-bootstrap-table2/src/row/row-pure-content.js
vendored
Normal file
116
packages/react-bootstrap-table2/src/row/row-pure-content.js
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/no-array-index-key: 0 */
|
||||
/* eslint no-plusplus: 0 */
|
||||
import React from 'react';
|
||||
|
||||
import _ from '../utils';
|
||||
import Cell from '../cell';
|
||||
|
||||
export default class RowPureContent extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (typeof nextProps.shouldUpdate !== 'undefined') {
|
||||
return nextProps.shouldUpdate;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
row,
|
||||
keyField,
|
||||
columns,
|
||||
rowIndex,
|
||||
editable,
|
||||
editingRowIdx,
|
||||
editingColIdx,
|
||||
onStart,
|
||||
clickToEdit,
|
||||
dbclickToEdit,
|
||||
EditingCellComponent,
|
||||
tabIndexStart
|
||||
} = this.props;
|
||||
|
||||
let tabIndex = tabIndexStart;
|
||||
|
||||
return columns.map((column, index) => {
|
||||
if (!column.hidden) {
|
||||
const { dataField } = column;
|
||||
const content = _.get(row, dataField);
|
||||
if (rowIndex === editingRowIdx && index === editingColIdx) {
|
||||
return (
|
||||
<EditingCellComponent
|
||||
key={ `${content}-${index}-editing` }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
column={ column }
|
||||
columnIndex={ index }
|
||||
/>
|
||||
);
|
||||
}
|
||||
// render cell
|
||||
let cellTitle;
|
||||
let cellStyle = {};
|
||||
const cellAttrs = {
|
||||
..._.isFunction(column.attrs)
|
||||
? column.attrs(content, row, rowIndex, index)
|
||||
: column.attrs,
|
||||
...column.events
|
||||
};
|
||||
|
||||
const cellClasses = _.isFunction(column.classes)
|
||||
? column.classes(content, row, rowIndex, index)
|
||||
: column.classes;
|
||||
|
||||
if (column.style) {
|
||||
cellStyle = _.isFunction(column.style)
|
||||
? column.style(content, row, rowIndex, index)
|
||||
: column.style;
|
||||
cellStyle = Object.assign({}, cellStyle) || {};
|
||||
}
|
||||
|
||||
if (column.title) {
|
||||
cellTitle = _.isFunction(column.title)
|
||||
? column.title(content, row, rowIndex, index)
|
||||
: content;
|
||||
cellAttrs.title = cellTitle;
|
||||
}
|
||||
|
||||
if (column.align) {
|
||||
cellStyle.textAlign =
|
||||
_.isFunction(column.align)
|
||||
? column.align(content, row, rowIndex, index)
|
||||
: column.align;
|
||||
}
|
||||
|
||||
if (cellClasses) cellAttrs.className = cellClasses;
|
||||
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
|
||||
|
||||
let editableCell = _.isDefined(column.editable) ? column.editable : true;
|
||||
if (column.dataField === keyField || !editable) editableCell = false;
|
||||
if (_.isFunction(column.editable)) {
|
||||
editableCell = column.editable(content, row, rowIndex, index);
|
||||
}
|
||||
|
||||
if (tabIndexStart !== -1) {
|
||||
cellAttrs.tabIndex = tabIndex++;
|
||||
}
|
||||
|
||||
return (
|
||||
<Cell
|
||||
key={ `${content}-${index}` }
|
||||
row={ row }
|
||||
editable={ editableCell }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ index }
|
||||
column={ column }
|
||||
onStart={ onStart }
|
||||
clickToEdit={ clickToEdit }
|
||||
dbclickToEdit={ dbclickToEdit }
|
||||
{ ...cellAttrs }
|
||||
/>
|
||||
);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
37
packages/react-bootstrap-table2/src/row/should-updater.js
vendored
Normal file
37
packages/react-bootstrap-table2/src/row/should-updater.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import _ from '../utils';
|
||||
|
||||
export default ExtendBase =>
|
||||
class RowShouldUpdater extends ExtendBase {
|
||||
shouldUpdateByCellEditing(nextProps) {
|
||||
if (!(this.props.clickToEdit || this.props.dbclickToEdit)) return false;
|
||||
return (
|
||||
nextProps.editingRowIdx === nextProps.rowIndex ||
|
||||
(this.props.editingRowIdx === nextProps.rowIndex &&
|
||||
nextProps.editingRowIdx === null)
|
||||
);
|
||||
}
|
||||
|
||||
shouldUpdatedBySelfProps(nextProps) {
|
||||
return (
|
||||
this.props.className !== nextProps.className ||
|
||||
!_.isEqual(this.props.style, nextProps.style) ||
|
||||
!_.isEqual(this.props.attrs, nextProps.attrs)
|
||||
);
|
||||
}
|
||||
|
||||
shouldUpdatedByNormalProps(nextProps) {
|
||||
const shouldUpdate =
|
||||
this.props.rowIndex !== nextProps.rowIndex ||
|
||||
this.props.editable !== nextProps.editable ||
|
||||
!_.isEqual(this.props.row, nextProps.row) ||
|
||||
this.props.columns.length !== nextProps.columns.length;
|
||||
|
||||
return shouldUpdate;
|
||||
}
|
||||
|
||||
shouldUpdateChild(nextProps) {
|
||||
return this.shouldUpdateByCellEditing(nextProps) ||
|
||||
this.shouldUpdatedByNormalProps(nextProps);
|
||||
}
|
||||
};
|
||||
64
packages/react-bootstrap-table2/src/row/simple-row.js
vendored
Normal file
64
packages/react-bootstrap-table2/src/row/simple-row.js
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint react/no-array-index-key: 0 */
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import RowPureContent from './row-pure-content';
|
||||
import eventDelegater from './event-delegater';
|
||||
import shouldUpdater from './should-updater';
|
||||
|
||||
class SimpleRow extends shouldUpdater(eventDelegater(Component)) {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.shouldUpdateRowContent = false;
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
this.shouldUpdateRowContent = false;
|
||||
this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps);
|
||||
if (this.shouldUpdateRowContent) return true;
|
||||
|
||||
return this.shouldUpdatedBySelfProps(nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
style,
|
||||
attrs,
|
||||
visibleColumnSize,
|
||||
tabIndexCell,
|
||||
...rest
|
||||
} = this.props;
|
||||
const trAttrs = this.delegate(attrs);
|
||||
const tabIndexStart = (this.props.rowIndex * visibleColumnSize) + 1;
|
||||
|
||||
return (
|
||||
<tr style={ style } className={ className } { ...trAttrs }>
|
||||
<RowPureContent
|
||||
shouldUpdate={ this.shouldUpdateRowContent }
|
||||
tabIndexStart={ tabIndexCell ? tabIndexStart : -1 }
|
||||
{ ...rest }
|
||||
/>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleRow.propTypes = {
|
||||
row: PropTypes.object.isRequired,
|
||||
rowIndex: PropTypes.number.isRequired,
|
||||
columns: PropTypes.array.isRequired,
|
||||
style: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
attrs: PropTypes.object
|
||||
};
|
||||
|
||||
SimpleRow.defaultProps = {
|
||||
editable: true,
|
||||
style: {},
|
||||
className: null,
|
||||
attrs: {}
|
||||
};
|
||||
|
||||
export default SimpleRow;
|
||||
@@ -6,7 +6,7 @@ export const getSelectionSummary = (
|
||||
keyField,
|
||||
selected = []
|
||||
) => {
|
||||
let allRowsSelected = true;
|
||||
let allRowsSelected = data.length > 0;
|
||||
let allRowsNotSelected = true;
|
||||
|
||||
const rowKeys = data.map(d => d[keyField]);
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
|
||||
import Body from '../src/body';
|
||||
import Row from '../src/row';
|
||||
import Row from '../src/row/simple-row';
|
||||
import RowAggregator from '../src/row/aggregate-row';
|
||||
import Const from '../src/const';
|
||||
import RowSection from '../src/row-section';
|
||||
import RowSection from '../src/row/row-section';
|
||||
import SelectionContext from '../src/contexts/selection-context';
|
||||
import ExpansionContext from '../src/contexts/row-expand-context';
|
||||
import mockBodyResolvedProps from './test-helpers/mock/body-resolved-props';
|
||||
|
||||
describe('Body', () => {
|
||||
@@ -169,92 +173,6 @@ describe('Body', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.style is defined', () => {
|
||||
const selectedRowKey = data[0][keyField];
|
||||
const selectedRowKeys = [selectedRowKey];
|
||||
const selectedStyle = { backgroundColor: 'green', fontWeight: 'bold' };
|
||||
const selectRow = { mode: 'radio', style: selectedStyle };
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField="id"
|
||||
columns={ columns }
|
||||
data={ data }
|
||||
rowStyle={ rowStyle }
|
||||
selectRow={ selectRow }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
/>);
|
||||
});
|
||||
|
||||
it('should rendering selected Row component with mixing selectRow.style correctly', () => {
|
||||
const selectedRow = wrapper.find(Row).get(0);
|
||||
expect(JSON.stringify(selectedRow.props.style)).toBe(JSON.stringify({
|
||||
...rowStyle,
|
||||
...selectedStyle
|
||||
}));
|
||||
});
|
||||
|
||||
describe('and selectRow.bgColor is also defined', () => {
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = 'gray';
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField="id"
|
||||
columns={ columns }
|
||||
data={ data }
|
||||
rowStyle={ rowStyle }
|
||||
selectRow={ selectRow }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
/>);
|
||||
});
|
||||
|
||||
it('should rendering selected Row component with mixing selectRow.style correctly', () => {
|
||||
const selectedRow = wrapper.find(Row).get(0);
|
||||
expect(JSON.stringify(selectedRow.props.style)).toBe(JSON.stringify({
|
||||
...rowStyle,
|
||||
...selectedStyle,
|
||||
backgroundColor: selectRow.bgColor
|
||||
}));
|
||||
});
|
||||
|
||||
it('should render selected Row component with correct style.backgroundColor', () => {
|
||||
const selectedRow = wrapper.find(Row).get(0);
|
||||
expect(selectedRow.props.style.backgroundColor).toEqual(selectRow.bgColor);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.bgColor is defined', () => {
|
||||
const selectedRowKey = data[0][keyField];
|
||||
const selectedRowKeys = [selectedRowKey];
|
||||
const selectRow = { mode: 'radio', bgColor: 'gray' };
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = 'gray';
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField="id"
|
||||
columns={ columns }
|
||||
data={ data }
|
||||
rowStyle={ rowStyle }
|
||||
selectRow={ selectRow }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
/>);
|
||||
});
|
||||
|
||||
it('should rendering selected Row component with correct style', () => {
|
||||
const selectedRow = wrapper.find(Row).get(0);
|
||||
expect(JSON.stringify(selectedRow.props.style)).toBe(JSON.stringify({
|
||||
...rowStyle,
|
||||
backgroundColor: selectRow.bgColor
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when rowClasses prop is defined', () => {
|
||||
@@ -310,31 +228,6 @@ describe('Body', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.classes is defined', () => {
|
||||
const selectedRowKey = data[0][keyField];
|
||||
const selectedRowKeys = [selectedRowKey];
|
||||
const selectedClasses = 'selected-classes';
|
||||
const selectRow = { mode: 'radio', classes: selectedClasses };
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField="id"
|
||||
columns={ columns }
|
||||
data={ data }
|
||||
rowClasses={ rowClasses }
|
||||
selectRow={ selectRow }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
/>);
|
||||
});
|
||||
|
||||
it('should rendering selected Row component with mixing selectRow.classes correctly', () => {
|
||||
const selectedRow = wrapper.find(Row).get(0);
|
||||
expect(selectedRow.props.className).toBe(`${rowClasses} ${selectedClasses}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when rowEvents prop is defined', () => {
|
||||
@@ -361,11 +254,14 @@ describe('Body', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when cellEdit.nonEditableRows props is defined', () => {
|
||||
const nonEditableRows = [data[1].id];
|
||||
describe('when cellEdit.createContext props is defined', () => {
|
||||
const EditingCellComponent = () => null;
|
||||
const RowComponent = props => <Row { ...props } />;
|
||||
const cellEdit = {
|
||||
mode: Const.CLICK_TO_CELL_EDIT,
|
||||
nonEditableRows
|
||||
options: { onStartEdit: jest.fn() },
|
||||
createContext: jest.fn(),
|
||||
createEditingCell: jest.fn().mockReturnValue(EditingCellComponent),
|
||||
withRowLevelCellEdit: jest.fn().mockReturnValue(RowComponent)
|
||||
};
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
@@ -379,259 +275,82 @@ describe('Body', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Row component with correct editable prop', () => {
|
||||
it('should render Row Component correctly', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
const rows = wrapper.find(Row);
|
||||
for (let i = 0; i < rows.length; i += 1) {
|
||||
if (nonEditableRows.indexOf(rows.get(i).props.row[keyField]) > -1) {
|
||||
expect(rows.get(i).props.editable).toBeFalsy();
|
||||
} else {
|
||||
expect(rows.get(i).props.editable).toBeTruthy();
|
||||
}
|
||||
}
|
||||
expect(cellEdit.createEditingCell).toHaveBeenCalledTimes(1);
|
||||
expect(cellEdit.withRowLevelCellEdit).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.find(RowComponent)).toHaveLength(2);
|
||||
const aRowElement = wrapper.find(RowComponent).get(0);
|
||||
expect(aRowElement.props.EditingCellComponent).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.mode is checkbox or radio (row was selectable)', () => {
|
||||
describe('when selectRow.mode is ROW_SELECT_DISABLED or expandRow.renderer is undefined', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('shouldn\'t render RowAggregator component', () => {
|
||||
expect(wrapper.find(RowAggregator)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.mode is defined correctly', () => {
|
||||
const selectRow = { mode: 'checkbox' };
|
||||
const selectedRowKey = data[0][keyField];
|
||||
const selectedRowKeys = [selectedRowKey];
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Row component with correct selected prop', () => {
|
||||
const rows = wrapper.find(Row);
|
||||
for (let i = 0; i < rows.length; i += 1) {
|
||||
const row = rows.get(i);
|
||||
expect(row.props.selected).toBe(selectedRowKeys.indexOf(row.props.row[keyField]) > -1);
|
||||
}
|
||||
});
|
||||
it('should render RowAggregator component correctly', () => {
|
||||
const rowAggregator = wrapper.find(RowAggregator);
|
||||
|
||||
describe('if selectRow.style is defined as an object', () => {
|
||||
const style = { backgroundColor: 'red' };
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.style = style;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Row component with correct style prop', () => {
|
||||
expect(JSON.stringify(wrapper.find(Row).get(0).props.style)).toBe(JSON.stringify(style));
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.style is defined as a function', () => {
|
||||
const style = { backgroundColor: 'red' };
|
||||
const styleCallBack = sinon.stub().returns(style);
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.style = styleCallBack;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should calling style callback correctly', () => {
|
||||
expect(styleCallBack.callCount).toBe(1);
|
||||
expect(styleCallBack.calledWith(data[0]), 1);
|
||||
});
|
||||
|
||||
it('should render Row component with correct style prop', () => {
|
||||
expect(JSON.stringify(wrapper.find(Row).get(0).props.style)).toBe(JSON.stringify(style));
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.classes is defined as a string', () => {
|
||||
const className = 'custom-class';
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.classes = className;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Row component with correct className prop', () => {
|
||||
expect(wrapper.find(Row).get(0).props.className).toEqual(className);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.classes is defined as a function', () => {
|
||||
const className = 'custom-class';
|
||||
const classesCallBack = sinon.stub().returns(className);
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.classes = classesCallBack;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should calling style callback correctly', () => {
|
||||
expect(classesCallBack.callCount).toBe(1);
|
||||
expect(classesCallBack.calledWith(data[0]), 1);
|
||||
});
|
||||
|
||||
it('should render Row component with correct style prop', () => {
|
||||
expect(wrapper.find(Row).get(0).props.className).toEqual(className);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.bgColor is defined as a string', () => {
|
||||
const bgColor = 'red';
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = bgColor;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Row component with correct style.backgroundColor prop', () => {
|
||||
expect(wrapper.find(Row).get(0).props.style).toEqual({ backgroundColor: bgColor });
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.bgColor is defined as a string', () => {
|
||||
const bgColor = 'red';
|
||||
const bgColorCallBack = sinon.stub().returns(bgColor);
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = bgColorCallBack;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should calling selectRow.bgColor callback correctly', () => {
|
||||
expect(bgColorCallBack.calledOnce).toBeTruthy();
|
||||
expect(bgColorCallBack.calledWith(data[0]), 1).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render Row component with correct style.backgroundColor prop', () => {
|
||||
expect(wrapper.find(Row).get(0).props.style).toEqual({ backgroundColor: bgColor });
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.bgColor defined and selectRow.style.backgroundColor defined', () => {
|
||||
const bgColor = 'yellow';
|
||||
const style = { backgroundColor: 'red' };
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.style = style;
|
||||
selectRow.bgColor = bgColor;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should take selectRow.bgColor as higher priority', () => {
|
||||
expect(wrapper.find(Row).get(0).props.style.backgroundColor).toBe(bgColor);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.nonSelectable is defined', () => {
|
||||
const nonSelectableRowIndex = 1;
|
||||
const nonSelectable = [data[nonSelectableRowIndex][keyField]];
|
||||
|
||||
beforeEach(() => {
|
||||
selectRow.nonSelectable = nonSelectable;
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ selectedRowKeys }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render Row component with correct selectable prop', () => {
|
||||
expect(wrapper.find(Row).get(0).props.selectable).toBeTruthy();
|
||||
expect(wrapper.find(Row).get(nonSelectableRowIndex).props.selectable).toBeFalsy();
|
||||
});
|
||||
expect(rowAggregator.get(0).props.selectRow.mode)
|
||||
.not.toEqual(Const.ROW_SELECT_DISABLED);
|
||||
expect(rowAggregator.get(0).props.selected).toBeDefined();
|
||||
expect(rowAggregator.get(0).props.selectable).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.mode is ROW_SELECT_DISABLED (row was un-selectable)', () => {
|
||||
describe('when expandRow.renderer is defined correctly', () => {
|
||||
const expandRow = { renderer: jest.fn() };
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
selectedRowKeys={ [] }
|
||||
/>
|
||||
wrapper = mount(
|
||||
<ExpansionContext.Provider data={ data } keyField={ keyField } expandRow={ expandRow }>
|
||||
<Body
|
||||
{ ...mockBodyResolvedProps }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
keyField={ keyField }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
</ExpansionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('prop selected should be null', () => {
|
||||
expect(wrapper.find(Row).get(0).props.selected).toBeNull();
|
||||
it('should render RowAggregator component correctly', () => {
|
||||
const rowAggregator = wrapper.find(RowAggregator);
|
||||
expect(rowAggregator.get(0).props.expandRow.renderer).toEqual(expandRow.renderer);
|
||||
expect(rowAggregator.get(0).props.expanded).toBeDefined();
|
||||
expect(rowAggregator.get(0).props.expandable).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -177,13 +177,35 @@ describe('Cell', () => {
|
||||
let props;
|
||||
let nextProps;
|
||||
|
||||
describe('when content is change', () => {
|
||||
describe('if column.isDummyField is false', () => {
|
||||
describe('when content is change', () => {
|
||||
const column = { dataField: 'name', text: 'Product Name' };
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
row,
|
||||
columnIndex: 1,
|
||||
rowIndex: 1,
|
||||
column
|
||||
};
|
||||
wrapper = shallow(
|
||||
<Cell { ...props } />);
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, row: { id: 1, name: 'CDE' } };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when props.tabIndex is change', () => {
|
||||
const column = { dataField: 'name', text: 'Product Name' };
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
row,
|
||||
columnIndex: 1,
|
||||
rowIndex: 1,
|
||||
tabIndex: 5,
|
||||
column
|
||||
};
|
||||
wrapper = shallow(
|
||||
@@ -191,11 +213,32 @@ describe('Cell', () => {
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, row: { id: 1, name: 'CDE' } };
|
||||
nextProps = { ...props, tabIndex: 2 };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if column.isDummyField is true', () => {
|
||||
describe('when content is change', () => {
|
||||
const column = { dataField: '', text: 'Product Name', isDummyField: true };
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
row,
|
||||
columnIndex: 1,
|
||||
rowIndex: 1,
|
||||
column
|
||||
};
|
||||
wrapper = shallow(
|
||||
<Cell { ...props } />);
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, row: { id: 1, name: 'CDE', test: 'This is new Field' } };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when column.hidden is change', () => {
|
||||
const column = { dataField: 'name', text: 'Product Name' };
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -111,7 +111,10 @@ describe('Context', () => {
|
||||
createContext: jest.fn().mockReturnValue({
|
||||
Provider: CellEditContext.Provider,
|
||||
Consumer: CellEditContext.Consumer
|
||||
})
|
||||
}),
|
||||
options: {},
|
||||
createEditingCell: jest.fn().mockReturnValue(() => null),
|
||||
withRowLevelCellEdit: jest.fn().mockReturnValue(() => null)
|
||||
};
|
||||
wrapper = shallow(
|
||||
<BootstrapTable
|
||||
|
||||
@@ -4,7 +4,7 @@ import { shallow } from 'enzyme';
|
||||
|
||||
import dataOperator from '../../src/store/operators';
|
||||
import BootstrapTable from '../../src/bootstrap-table';
|
||||
import createSelectionContext from '../../src/contexts/selection-context';
|
||||
import SelectionContext from '../../src/contexts/selection-context';
|
||||
|
||||
describe('DataContext', () => {
|
||||
let wrapper;
|
||||
@@ -42,7 +42,6 @@ describe('DataContext', () => {
|
||||
const defaultSelectRow = {
|
||||
mode: 'checkbox'
|
||||
};
|
||||
const SelectionContext = createSelectionContext(dataOperator);
|
||||
|
||||
function shallowContext(selectRow = defaultSelectRow) {
|
||||
return (
|
||||
@@ -81,9 +80,13 @@ describe('DataContext', () => {
|
||||
it('should pass correct sort props to children element', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(mockBase).toHaveBeenCalledWith({
|
||||
...defaultSelectRow,
|
||||
selected: wrapper.state().selected,
|
||||
onRowSelect: wrapper.instance().handleRowSelect,
|
||||
onAllRowsSelect: wrapper.instance().handleAllRowsSelect
|
||||
onAllRowsSelect: wrapper.instance().handleAllRowsSelect,
|
||||
allRowsNotSelected: true,
|
||||
allRowsSelected: false,
|
||||
checkedStatus: 'unchecked'
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -220,6 +223,25 @@ describe('DataContext', () => {
|
||||
it('should set state.selected correctly', () => {
|
||||
expect(wrapper.state('selected')).toEqual(data.map(d => d[keyField]));
|
||||
});
|
||||
|
||||
describe('when selectRow.onSelectAll is defined', () => {
|
||||
const onSelectAll = jest.fn();
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
...defaultSelectRow,
|
||||
onSelectAll
|
||||
}));
|
||||
wrapper.instance().handleAllRowsSelect(e, false);
|
||||
});
|
||||
|
||||
it('should call selectRow.onSelectAll correctly', () => {
|
||||
expect(onSelectAll).toHaveBeenCalledWith(
|
||||
true,
|
||||
dataOperator.getSelectedRows(data, keyField, wrapper.state('selected')),
|
||||
e
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when isUnSelect argument is true', () => {
|
||||
@@ -234,24 +256,25 @@ describe('DataContext', () => {
|
||||
it('should set state.selected correctly', () => {
|
||||
expect(wrapper.state('selected')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.onSelectAll is defined', () => {
|
||||
const onSelectAll = jest.fn();
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
...defaultSelectRow,
|
||||
onSelectAll
|
||||
}));
|
||||
wrapper.instance().handleAllRowsSelect(e, false);
|
||||
});
|
||||
describe('when selectRow.onSelectAll is defined', () => {
|
||||
const onSelectAll = jest.fn();
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(shallowContext({
|
||||
...defaultSelectRow,
|
||||
selected: data.map(d => d[keyField]),
|
||||
onSelectAll
|
||||
}));
|
||||
wrapper.instance().handleAllRowsSelect(e, true);
|
||||
});
|
||||
|
||||
it('should call selectRow.onSelectAll correctly', () => {
|
||||
expect(onSelectAll).toHaveBeenCalledWith(
|
||||
true,
|
||||
dataOperator.getSelectedRows(data, keyField, wrapper.state('selected')),
|
||||
e
|
||||
);
|
||||
it('should call selectRow.onSelectAll correctly', () => {
|
||||
expect(onSelectAll).toHaveBeenCalledWith(
|
||||
false,
|
||||
dataOperator.getSelectedRows(data, keyField, data.map(d => d[keyField])),
|
||||
e
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -403,6 +403,24 @@ describe('HeaderCell', () => {
|
||||
it('header should render SortSymbol as default', () => {
|
||||
expect(wrapper.find(SortSymbol).length).toBe(1);
|
||||
});
|
||||
|
||||
describe('when sortCaret is defined ', () => {
|
||||
beforeEach(() => {
|
||||
column = { ...column, sortCaret: jest.fn() };
|
||||
wrapper = shallow(
|
||||
<HeaderCell column={ column } index={ index } onSort={ onSortCallBack } />
|
||||
);
|
||||
});
|
||||
|
||||
it('header should not render SortSymbol', () => {
|
||||
expect(wrapper.find(SortSymbol).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should call column.sortCaret correctly', () => {
|
||||
expect(column.sortCaret).toHaveBeenCalledTimes(1);
|
||||
expect(column.sortCaret).toHaveBeenCalledWith(undefined, column);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and sorting prop is true', () => {
|
||||
@@ -420,6 +438,30 @@ describe('HeaderCell', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sortCaret is defined ', () => {
|
||||
beforeEach(() => {
|
||||
column = { ...column, sortCaret: jest.fn() };
|
||||
wrapper = shallow(
|
||||
<HeaderCell
|
||||
column={ column }
|
||||
index={ index }
|
||||
onSort={ onSortCallBack }
|
||||
sortOrder={ Const.SORT_ASC }
|
||||
sorting
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('header should not render SortSymbol', () => {
|
||||
expect(wrapper.find(SortSymbol).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should call column.sortCaret correctly', () => {
|
||||
expect(column.sortCaret).toHaveBeenCalledTimes(1);
|
||||
expect(column.sortCaret).toHaveBeenCalledWith(Const.SORT_ASC, column);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when headerSortingClasses is defined ', () => {
|
||||
const classes = 'foo';
|
||||
const order = Const.SORT_DESC;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
|
||||
import HeaderCell from '../src/header-cell';
|
||||
import SelectionHeaderCell from '../src//row-selection/selection-header-cell';
|
||||
import SelectionHeaderCell from '../src/row-selection/selection-header-cell';
|
||||
import ExpandHeaderCell from '../src/row-expand/expand-header-cell';
|
||||
import SelectionContext from '../src/contexts/selection-context';
|
||||
import ExpansionContext from '../src/contexts/row-expand-context';
|
||||
import Header from '../src/header';
|
||||
import Const from '../src/const';
|
||||
import mockHeaderResolvedProps from './test-helpers/mock/header-resolved-props';
|
||||
@@ -17,6 +21,16 @@ describe('Header', () => {
|
||||
text: 'Name'
|
||||
}];
|
||||
|
||||
const data = [{
|
||||
id: 1,
|
||||
name: 'A'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'B'
|
||||
}];
|
||||
|
||||
const keyField = 'id';
|
||||
|
||||
describe('simplest header', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<Header { ...mockHeaderResolvedProps } columns={ columns } />);
|
||||
@@ -89,12 +103,18 @@ describe('Header', () => {
|
||||
describe('when selectRow.mode is radio (single selection)', () => {
|
||||
beforeEach(() => {
|
||||
const selectRow = { mode: 'radio' };
|
||||
wrapper = shallow(
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider
|
||||
data={ data }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
>
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -105,12 +125,18 @@ describe('Header', () => {
|
||||
describe('when selectRow.hideSelectColumn is true', () => {
|
||||
beforeEach(() => {
|
||||
const selectRow = { mode: 'radio', hideSelectColumn: true };
|
||||
wrapper = shallow(
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider
|
||||
data={ data }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
>
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -146,12 +172,18 @@ describe('Header', () => {
|
||||
describe('when selectRow.mode is checkbox (multiple selection)', () => {
|
||||
beforeEach(() => {
|
||||
const selectRow = { mode: 'checkbox' };
|
||||
wrapper = shallow(
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider
|
||||
data={ data }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
>
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -162,12 +194,18 @@ describe('Header', () => {
|
||||
describe('when selectRow.hideSelectColumn is true', () => {
|
||||
beforeEach(() => {
|
||||
const selectRow = { mode: 'checkbox', hideSelectColumn: true };
|
||||
wrapper = shallow(
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider
|
||||
data={ data }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
>
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -177,4 +215,44 @@ describe('Header', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('expandRow', () => {
|
||||
describe('when expandRow.showExpandColumn is false', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render <ExpandHeaderCell />', () => {
|
||||
expect(wrapper.find(ExpandHeaderCell).length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when expandRow.showExpandColumn is true', () => {
|
||||
beforeEach(() => {
|
||||
const expandRow = { renderer: jest.fn(), expanded: [], showExpandColumn: true };
|
||||
wrapper = mount(
|
||||
<ExpansionContext.Provider
|
||||
data={ data }
|
||||
keyField={ keyField }
|
||||
expandRow={ expandRow }
|
||||
>
|
||||
<Header
|
||||
{ ...mockHeaderResolvedProps }
|
||||
columns={ columns }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
</ExpansionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should render <ExpandHeaderCell /> correctly', () => {
|
||||
expect(wrapper.find(ExpandHeaderCell).length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import React, { Component } from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { extendTo } from '../test-helpers/mock-component';
|
||||
import baseResolver from '../../src/props-resolver/index';
|
||||
import Const from '../../src/const';
|
||||
|
||||
describe('TableResolver', () => {
|
||||
const keyField = 'id';
|
||||
@@ -71,231 +69,4 @@ describe('TableResolver', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveSelectRowProps', () => {
|
||||
let cellSelectionInfo;
|
||||
let selectRow;
|
||||
|
||||
describe('if selectRow was not defined', () => {
|
||||
beforeEach(() => {
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
cellSelectionInfo = wrapper.instance().resolveSelectRowProps();
|
||||
});
|
||||
|
||||
it('should return object', () => {
|
||||
expect(cellSelectionInfo).toBeDefined();
|
||||
expect(cellSelectionInfo.constructor).toEqual(Object);
|
||||
});
|
||||
|
||||
it('should contain mode in ROW_SELECT_DISABLED', () => {
|
||||
expect(cellSelectionInfo.mode).toEqual(Const.ROW_SELECT_DISABLED);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow was defined', () => {
|
||||
describe('when mode was defined', () => {
|
||||
it('should return object which contains ROW_SELECT_SINGLE if mode is radio', () => {
|
||||
selectRow = { mode: 'radio' };
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectRow
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
cellSelectionInfo = wrapper.instance().resolveSelectRowProps();
|
||||
|
||||
expect(cellSelectionInfo).toBeDefined();
|
||||
expect(cellSelectionInfo.constructor).toEqual(Object);
|
||||
expect(cellSelectionInfo.mode).toEqual(Const.ROW_SELECT_SINGLE);
|
||||
});
|
||||
|
||||
it('should return object which contains ROW_SELECT_MULTIPLE if mode is checkbox', () => {
|
||||
selectRow = { mode: 'checkbox' };
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectRow
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
cellSelectionInfo = wrapper.instance().resolveSelectRowProps();
|
||||
|
||||
expect(cellSelectionInfo).toBeDefined();
|
||||
expect(cellSelectionInfo.constructor).toEqual(Object);
|
||||
expect(cellSelectionInfo.mode).toEqual(Const.ROW_SELECT_MULTIPLE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when options were given', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = {};
|
||||
const mockOptions = {
|
||||
foo: 'test',
|
||||
bar: sinon.stub()
|
||||
};
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectRow
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
cellSelectionInfo = wrapper.instance().resolveSelectRowProps(mockOptions);
|
||||
});
|
||||
|
||||
it('should return object which contain options', () => {
|
||||
expect(cellSelectionInfo).toEqual(expect.objectContaining({
|
||||
foo: 'test',
|
||||
bar: expect.any(Function)
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveSelectRowPropsForHeader', () => {
|
||||
let headerCellSelectionInfo;
|
||||
let selectRow;
|
||||
|
||||
beforeEach(() => {
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader();
|
||||
});
|
||||
|
||||
describe('if selectRow was not defined', () => {
|
||||
it('should return object', () => {
|
||||
expect(headerCellSelectionInfo).toBeDefined();
|
||||
expect(headerCellSelectionInfo.constructor).toEqual(Object);
|
||||
});
|
||||
|
||||
it('should contain mode in ROW_SELECT_DISABLED', () => {
|
||||
expect(headerCellSelectionInfo.mode).toEqual(Const.ROW_SELECT_DISABLED);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow was defined', () => {
|
||||
describe('when mode was defined', () => {
|
||||
it('should return object which contains ROW_SELECT_SINGLE if mode is radio', () => {
|
||||
selectRow = { mode: 'radio' };
|
||||
const selectedRowKeys = [];
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectedRowKeys, selectRow
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader();
|
||||
|
||||
expect(headerCellSelectionInfo).toBeDefined();
|
||||
expect(headerCellSelectionInfo.constructor).toEqual(Object);
|
||||
expect(headerCellSelectionInfo.mode).toEqual(Const.ROW_SELECT_SINGLE);
|
||||
});
|
||||
|
||||
it('should return object which contains ROW_SELECT_MULTIPLE if mode is checkbox', () => {
|
||||
selectRow = { mode: 'checkbox' };
|
||||
const selectedRowKeys = [];
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectedRowKeys, selectRow
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader();
|
||||
|
||||
expect(headerCellSelectionInfo).toBeDefined();
|
||||
expect(headerCellSelectionInfo.constructor).toEqual(Object);
|
||||
expect(headerCellSelectionInfo.mode).toEqual(Const.ROW_SELECT_MULTIPLE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when options were given', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = {};
|
||||
const mockOptions = {
|
||||
foo: 'test',
|
||||
bar: sinon.stub(),
|
||||
allRowsSelected: false,
|
||||
selected: []
|
||||
};
|
||||
const selectedRowKeys = [];
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectedRowKeys, selectRow
|
||||
}, null);
|
||||
wrapper = shallow(mockElement);
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader(mockOptions);
|
||||
});
|
||||
|
||||
it('should return object which contain specified options', () => {
|
||||
expect(headerCellSelectionInfo).toEqual(expect.objectContaining({
|
||||
foo: 'test',
|
||||
bar: expect.any(Function)
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('if options.allRowsSelected is true', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = {};
|
||||
const selectedRowKeys = [1, 2];
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectRow
|
||||
}, null);
|
||||
|
||||
wrapper = shallow(mockElement);
|
||||
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader({
|
||||
allRowsSelected: true,
|
||||
selected: selectedRowKeys
|
||||
});
|
||||
});
|
||||
|
||||
it('should return checkedStatus which eqauls to checked', () => {
|
||||
expect(headerCellSelectionInfo).toEqual(expect.objectContaining({
|
||||
checkedStatus: Const.CHECKBOX_STATUS_CHECKED
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('if options.allRowsSelected and options.allRowsNotSelected both are false', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = {};
|
||||
const selectedRowKeys = [1];
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectRow
|
||||
}, null);
|
||||
|
||||
wrapper = shallow(mockElement);
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader({
|
||||
allRowsSelected: false,
|
||||
allRowsNotSelected: false,
|
||||
selected: selectedRowKeys
|
||||
});
|
||||
});
|
||||
|
||||
it('should return checkedStatus which eqauls to indeterminate', () => {
|
||||
expect(headerCellSelectionInfo).toEqual(expect.objectContaining({
|
||||
checkedStatus: Const.CHECKBOX_STATUS_INDETERMINATE
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('if options.allRowsNotSelected is true', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = {};
|
||||
const selectedRowKeys = [];
|
||||
const mockElement = React.createElement(BootstrapTableMock, {
|
||||
data, keyField, columns, selectRow
|
||||
}, null);
|
||||
|
||||
wrapper = shallow(mockElement);
|
||||
|
||||
headerCellSelectionInfo = wrapper.instance().resolveSelectRowPropsForHeader({
|
||||
allRowsSelected: false,
|
||||
allRowsNotSelected: true,
|
||||
selected: selectedRowKeys
|
||||
});
|
||||
});
|
||||
|
||||
it('should return checkedStatus which eqauls to unchecked', () => {
|
||||
expect(headerCellSelectionInfo).toEqual(expect.objectContaining({
|
||||
checkedStatus: Const.CHECKBOX_STATUS_UNCHECKED
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
import 'jsdom-global/register';
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import SelectionContext from '../../src/contexts/selection-context';
|
||||
import withSelectionConsumer from '../../src/row-selection/row-consumer';
|
||||
|
||||
describe('withSelectionConsumer', () => {
|
||||
let wrapper;
|
||||
let selectRow;
|
||||
const BaseComponent = () => null;
|
||||
const WithSelectionComponent = withSelectionConsumer(props => <BaseComponent { ...props } />);
|
||||
|
||||
const data = [{
|
||||
id: 1,
|
||||
name: 'A'
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'B'
|
||||
}, {
|
||||
id: 3,
|
||||
name: 'C'
|
||||
}];
|
||||
const rowIndex = 1;
|
||||
const row = data[rowIndex];
|
||||
const keyField = 'id';
|
||||
const value = row[keyField];
|
||||
|
||||
describe('if current row is selected', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', selected: [data[rowIndex][keyField]] };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject selected prop as true to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('selected')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if current row is not selected', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', selected: [] };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject selected prop as false to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('selected')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if current row is selectable', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', nonSelectable: [] };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject selectable prop as true to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('selectable')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if current row is non selectable', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', nonSelectable: [data[rowIndex][keyField]] };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject selectable prop as false to target component', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('selectable')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if current row is selected', () => {
|
||||
const selectedStyle = { backgroundColor: 'green', fontWeight: 'bold' };
|
||||
describe('when selectRow.style is defined as an object', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', selected: [data[rowIndex][keyField]], style: selectedStyle };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual(selectedStyle);
|
||||
});
|
||||
|
||||
describe('and props.style is also defined', () => {
|
||||
const componentStype = { fontSize: '16px' };
|
||||
beforeEach(() => {
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
style={ componentStype }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual({
|
||||
...selectedStyle,
|
||||
...componentStype
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and selectRow.bgColor is also defined as an object', () => {
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = 'gray';
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop with correct backgroundColor', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual({
|
||||
...selectedStyle,
|
||||
backgroundColor: selectRow.bgColor
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and selectRow.bgColor is also defined as a function', () => {
|
||||
const color = 'gray';
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = jest.fn().mockReturnValue(color);
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop with correct backgroundColor', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual({
|
||||
...selectedStyle,
|
||||
backgroundColor: color
|
||||
});
|
||||
});
|
||||
|
||||
it('should call selectRow.bgColor function correctly', () => {
|
||||
expect(selectRow.bgColor).toHaveBeenCalledTimes(1);
|
||||
expect(selectRow.bgColor).toHaveBeenCalledWith(row, rowIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.style is defined as a function', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', selected: [data[rowIndex][keyField]], style: jest.fn().mockReturnValue(selectedStyle) };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual(selectedStyle);
|
||||
});
|
||||
|
||||
it('should call selectRow.style function correctly', () => {
|
||||
expect(selectRow.style).toHaveBeenCalledTimes(1);
|
||||
expect(selectRow.style).toHaveBeenCalledWith(row, rowIndex);
|
||||
});
|
||||
|
||||
describe('and props.style is also defined', () => {
|
||||
const componentStype = { fontSize: '16px' };
|
||||
beforeEach(() => {
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
style={ componentStype }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual({
|
||||
...selectedStyle,
|
||||
...componentStype
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and selectRow.bgColor is also defined as an object', () => {
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = 'gray';
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop with correct backgroundColor', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual({
|
||||
...selectedStyle,
|
||||
backgroundColor: selectRow.bgColor
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and selectRow.bgColor is also defined as a function', () => {
|
||||
const color = 'gray';
|
||||
beforeEach(() => {
|
||||
selectRow.bgColor = jest.fn().mockReturnValue(color);
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop with correct backgroundColor', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('style')).toEqual({
|
||||
...selectedStyle,
|
||||
backgroundColor: color
|
||||
});
|
||||
});
|
||||
|
||||
it('should call selectRow.bgColor function correctly', () => {
|
||||
expect(selectRow.bgColor).toHaveBeenCalledTimes(1);
|
||||
expect(selectRow.bgColor).toHaveBeenCalledWith(row, rowIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if current row is selected', () => {
|
||||
const selectedClassName = 'select-classname';
|
||||
describe('when selectRow.style is defined as an object', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', selected: [data[rowIndex][keyField]], classes: selectedClassName };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject className prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('className')).toEqual(selectedClassName);
|
||||
});
|
||||
|
||||
describe('and props.className is also defined', () => {
|
||||
const componentClassName = 'component-classname';
|
||||
beforeEach(() => {
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
className={ componentClassName }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('className')).toEqual(`${componentClassName} ${selectedClassName}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.style is defined as a function', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', selected: [data[rowIndex][keyField]], classes: jest.fn().mockReturnValue(selectedClassName) };
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject className prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('className')).toEqual(selectedClassName);
|
||||
});
|
||||
|
||||
it('should call selectRow.classes function correctly', () => {
|
||||
expect(selectRow.classes).toHaveBeenCalledTimes(1);
|
||||
expect(selectRow.classes).toHaveBeenCalledWith(row, rowIndex);
|
||||
});
|
||||
|
||||
describe('and props.className is also defined', () => {
|
||||
const componentClassName = 'component-classname';
|
||||
beforeEach(() => {
|
||||
wrapper = mount(
|
||||
<SelectionContext.Provider data={ data } keyField={ keyField } selectRow={ selectRow }>
|
||||
<WithSelectionComponent
|
||||
row={ row }
|
||||
value={ value }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
className={ componentClassName }
|
||||
/>
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
it('should inject style prop correctly', () => {
|
||||
expect(wrapper.find(BaseComponent)).toHaveLength(1);
|
||||
expect(wrapper.find(BaseComponent).prop('className')).toEqual(`${componentClassName} ${selectedClassName}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -14,24 +14,106 @@ describe('<SelectionCell />', () => {
|
||||
let wrapper;
|
||||
|
||||
describe('shouldComponentUpdate', () => {
|
||||
const selected = true;
|
||||
let props;
|
||||
let nextProps;
|
||||
|
||||
describe('when selected prop has not been changed', () => {
|
||||
it('should not update component', () => {
|
||||
const nextProps = { selected };
|
||||
describe('when selected prop has been changed', () => {
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
selected: false,
|
||||
mode,
|
||||
rowIndex,
|
||||
disabled: false,
|
||||
rowKey: 1
|
||||
};
|
||||
wrapper = shallow(
|
||||
<SelectionCell { ...props } />
|
||||
);
|
||||
});
|
||||
|
||||
wrapper = shallow(<SelectionCell rowKey={ 1 } mode={ mode } selected={ selected } />);
|
||||
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(false);
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, selected: true };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selected prop has been changed', () => {
|
||||
it('should update component', () => {
|
||||
const nextProps = { selected: !selected };
|
||||
describe('when rowIndex prop has been changed', () => {
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
selected: false,
|
||||
mode,
|
||||
rowIndex,
|
||||
disabled: false,
|
||||
rowKey: 1
|
||||
};
|
||||
wrapper = shallow(
|
||||
<SelectionCell { ...props } />
|
||||
);
|
||||
});
|
||||
|
||||
wrapper = shallow(<SelectionCell rowKey={ 1 } mode={ mode } selected={ selected } />);
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, rowIndex: 2 };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when tabIndex prop has been changed', () => {
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
selected: false,
|
||||
mode,
|
||||
rowIndex,
|
||||
disabled: false,
|
||||
tabIndex: 0,
|
||||
rowKey: 1
|
||||
};
|
||||
wrapper = shallow(
|
||||
<SelectionCell { ...props } />
|
||||
);
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, tabIndex: 2 };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when disabled prop has been changed', () => {
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
selected: false,
|
||||
mode,
|
||||
rowIndex,
|
||||
disabled: false,
|
||||
rowKey: 1
|
||||
};
|
||||
wrapper = shallow(
|
||||
<SelectionCell { ...props } />
|
||||
);
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, disabled: true };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when rowKey prop has been changed', () => {
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
selected: false,
|
||||
mode,
|
||||
rowIndex,
|
||||
disabled: false,
|
||||
rowKey: 1
|
||||
};
|
||||
wrapper = shallow(
|
||||
<SelectionCell { ...props } />
|
||||
);
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
nextProps = { ...props, rowKey: '1' };
|
||||
expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -104,6 +104,22 @@ describe('<SelectionHeaderCell />', () => {
|
||||
});
|
||||
|
||||
describe('render', () => {
|
||||
describe('when props.hideSelectAll is true', () => {
|
||||
beforeEach(() => {
|
||||
const checkedStatus = Const.CHECKBOX_STATUS_CHECKED;
|
||||
|
||||
wrapper = shallow(
|
||||
<SelectionHeaderCell mode="checkbox" checkedStatus={ checkedStatus } hideSelectAll />
|
||||
);
|
||||
});
|
||||
|
||||
it('should render empty th element', () => {
|
||||
expect(wrapper.find('th').length).toBe(1);
|
||||
expect(wrapper.find('th[data-row-selection]').length).toBe(1);
|
||||
expect(wrapper.find(CheckBox).length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when props.mode is radio', () => {
|
||||
beforeEach(() => {
|
||||
const checkedStatus = Const.CHECKBOX_STATUS_CHECKED;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user