mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2025-10-16 11:55:39 +00:00
fix #111
* implement selectRow.clickToSelect and selectRow.clickToEdit * add selectRow.clickToSelect and selectRow.clickToEdit stories * add clickToSelect to row selection examples for easier to select row * refine selectRow.nonSelectable * patch tests for selectRow.clickToSelect and selectRow.clickToEdit * patch docs for selectRow.clickToSelect and selectRow.clickToEdit
This commit is contained in:
parent
bbeb122af1
commit
985a1713ae
@ -13,6 +13,8 @@ The following are available properties in `selectRow`:
|
||||
* [classes)](#classes)
|
||||
* [bgColor](#bgColor)
|
||||
* [nonSelectable)](#nonSelectable)
|
||||
* [clickToSelect)](#clickToSelect)
|
||||
* [clickToEdit](#clickToEdit)
|
||||
|
||||
#### Optional
|
||||
|
||||
@ -118,4 +120,28 @@ const selectRow = {
|
||||
mode: 'checkbox',
|
||||
nonSelectable: [1, 3 ,5]
|
||||
};
|
||||
```
|
||||
|
||||
## <a name='clickToSelect'>selectRow.clickToSelect - [Bool]</a>
|
||||
Able to select row when clicking on row.
|
||||
|
||||
```js
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
```
|
||||
|
||||
> Note: if you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing
|
||||
> If you want to click on row to select row and edit cell simultaneously, you are suppose to enable [`selectRow.clickToEdit`](#clickToEdit)
|
||||
|
||||
## <a name='clickToEdit'>selectRow.clickToEdit - [Bool]</a>
|
||||
Able to click to edit cell and select row
|
||||
|
||||
```js
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
clickToEdit: true
|
||||
};
|
||||
```
|
||||
65
packages/react-bootstrap-table2-example/examples/row-selection/click-to-select-with-cell-edit.js
vendored
Normal file
65
packages/react-bootstrap-table2-example/examples/row-selection/click-to-select-with-cell-edit.js
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table2';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToEdit: true
|
||||
};
|
||||
|
||||
const cellEdit = {
|
||||
mode: 'click'
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToEdit: true // Click to edit cell also
|
||||
};
|
||||
|
||||
const cellEdit = {
|
||||
mode: 'click'
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } cellEdit={ cellEdit } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
55
packages/react-bootstrap-table2-example/examples/row-selection/click-to-select.js
vendored
Normal file
55
packages/react-bootstrap-table2-example/examples/row-selection/click-to-select.js
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
import React from 'react';
|
||||
|
||||
import BootstrapTable from 'react-bootstrap-table2';
|
||||
import Code from 'components/common/code-block';
|
||||
import { productsGenerator } from 'utils/common';
|
||||
|
||||
const products = productsGenerator();
|
||||
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
const columns = [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
@ -17,8 +17,9 @@ const columns = [{
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRowProp = {
|
||||
mode: 'checkbox'
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
@ -33,21 +34,22 @@ const columns = [{
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRowProp = {
|
||||
mode: 'checkbox'
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRowProp }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRowProp } />
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -19,6 +19,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
nonSelectable: [0, 2, 4]
|
||||
};
|
||||
|
||||
@ -36,6 +37,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
nonSelectable: [0, 2, 4]
|
||||
};
|
||||
|
||||
|
||||
@ -20,11 +20,13 @@ const columns = [{
|
||||
|
||||
const selectRow1 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
bgColor: '#00BFFF'
|
||||
};
|
||||
|
||||
const selectRow2 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
bgColor: (row, rowIndex) => (rowIndex > 1 ? '#00BFFF' : '#00FFFF')
|
||||
};
|
||||
|
||||
@ -42,6 +44,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
bgColor: '#00BFFF'
|
||||
};
|
||||
|
||||
@ -67,6 +70,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
bgColor: (row, rowIndex) => (rowIndex > 1 ? '#00BFFF' : '#00FFFF')
|
||||
};
|
||||
|
||||
|
||||
@ -20,11 +20,13 @@ const columns = [{
|
||||
|
||||
const selectRow1 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
classes: 'selection-row'
|
||||
};
|
||||
|
||||
const selectRow2 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
classes: (row, rowIndex) =>
|
||||
(rowIndex > 1 ? 'row-index-bigger-than-2101' : 'row-index-small-than-2101')
|
||||
};
|
||||
@ -43,6 +45,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
classes: 'selection-row'
|
||||
};
|
||||
|
||||
@ -68,6 +71,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
classes: (row, rowIndex) =>
|
||||
(rowIndex > 1 ? 'row-index-bigger-than-2101' : 'row-index-small-than-2101')
|
||||
};
|
||||
|
||||
@ -20,11 +20,13 @@ const columns = [{
|
||||
|
||||
const selectRow1 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
style: { backgroundColor: '#c8e6c9' }
|
||||
};
|
||||
|
||||
const selectRow2 = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
style: (row, rowIndex) => {
|
||||
const backgroundColor = rowIndex > 1 ? '#00BFFF' : '#00FFFF';
|
||||
return { backgroundColor };
|
||||
@ -45,6 +47,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
style: { backgroundColor: '#c8e6c9' }
|
||||
};
|
||||
|
||||
@ -70,6 +73,7 @@ const columns = [{
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
style: (row, rowIndex) => {
|
||||
const backgroundColor = rowIndex > 1 ? '#00BFFF' : '#00FFFF';
|
||||
return { backgroundColor };
|
||||
|
||||
@ -17,8 +17,9 @@ const columns = [{
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRowProp = {
|
||||
mode: 'radio'
|
||||
const selectRow = {
|
||||
mode: 'radio',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
const sourceCode = `\
|
||||
@ -33,21 +34,22 @@ const columns = [{
|
||||
text: 'Product Price'
|
||||
}];
|
||||
|
||||
const selectRowProp = {
|
||||
mode: 'radio'
|
||||
const selectRow = {
|
||||
mode: 'radio',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
<BootstrapTable
|
||||
keyField='id'
|
||||
data={ products }
|
||||
columns={ columns }
|
||||
selectRow={ selectRowProp }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
`;
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRowProp } />
|
||||
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
|
||||
<Code>{ sourceCode }</Code>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -53,6 +53,8 @@ import CellEditWithRedux from 'examples/cell-edit/cell-edit-with-redux-table';
|
||||
// work on row selection
|
||||
import SingleSelectionTable from 'examples/row-selection/single-selection';
|
||||
import MultipleSelectionTable from 'examples/row-selection/multiple-selection';
|
||||
import ClickToSelectTable from 'examples/row-selection/click-to-select';
|
||||
import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit';
|
||||
import SelectionStyleTable from 'examples/row-selection/selection-style';
|
||||
import SelectionClassTable from 'examples/row-selection/selection-class';
|
||||
import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows';
|
||||
@ -119,6 +121,8 @@ storiesOf('Cell Editing', module)
|
||||
storiesOf('Row Selection', module)
|
||||
.add('Single Selection', () => <SingleSelectionTable />)
|
||||
.add('Multiple Selection', () => <MultipleSelectionTable />)
|
||||
.add('Click to Select', () => <ClickToSelectTable />)
|
||||
.add('Click to Select and Edit Cell', () => <ClickToSelectWithCellEditTable />)
|
||||
.add('Selection Style', () => <SelectionStyleTable />)
|
||||
.add('Selection Class', () => <SelectionClassTable />)
|
||||
.add('Selection Background Color', () => <SelectionBgColorTable />)
|
||||
|
||||
6
packages/react-bootstrap-table2/src/body.js
vendored
6
packages/react-bootstrap-table2/src/body.js
vendored
@ -25,7 +25,8 @@ const Body = (props) => {
|
||||
const {
|
||||
style: selectedStyle,
|
||||
classes: selectedClasses,
|
||||
bgColor
|
||||
bgColor,
|
||||
nonSelectable
|
||||
} = selectRow;
|
||||
|
||||
let content;
|
||||
@ -55,6 +56,8 @@ const Body = (props) => {
|
||||
}
|
||||
}
|
||||
|
||||
const selectable = !nonSelectable || !nonSelectable.includes(key);
|
||||
|
||||
return (
|
||||
<Row
|
||||
key={ key }
|
||||
@ -64,6 +67,7 @@ const Body = (props) => {
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
editable={ editable }
|
||||
selectable={ selectable }
|
||||
selected={ selected }
|
||||
selectRow={ selectRow }
|
||||
style={ style }
|
||||
|
||||
@ -128,6 +128,8 @@ BootstrapTable.propTypes = {
|
||||
}),
|
||||
selectRow: PropTypes.shape({
|
||||
mode: PropTypes.oneOf([Const.ROW_SELECT_SINGLE, Const.ROW_SELECT_MULTIPLE]).isRequired,
|
||||
clickToSelect: PropTypes.bool,
|
||||
clickToEdit: PropTypes.bool,
|
||||
style: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
classes: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
nonSelectable: PropTypes.array,
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
/* eslint arrow-body-style: 0 */
|
||||
/* eslint react/prop-types: 0 */
|
||||
/* eslint no-return-assign: 0 */
|
||||
/* eslint class-methods-use-this: 0 */
|
||||
/* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */
|
||||
import React, { Component } from 'react';
|
||||
import cs from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
@ -16,6 +18,7 @@ class EditingCell extends Component {
|
||||
this.indicatorTimer = null;
|
||||
this.clearTimer = this.clearTimer.bind(this);
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||
this.beforeComplete = this.beforeComplete.bind(this);
|
||||
this.state = {
|
||||
@ -94,6 +97,15 @@ class EditingCell extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
if (e.target.tagName !== 'TD') {
|
||||
// To avoid the row selection event be triggered,
|
||||
// When user define selectRow.clickToSelect and selectRow.clickToEdit
|
||||
// We shouldn't trigger selection event even if user click on the cell editor(input)
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { invalidMessage } = this.state;
|
||||
const { row, column, className, style } = this.props;
|
||||
@ -111,6 +123,7 @@ class EditingCell extends Component {
|
||||
<td
|
||||
className={ cs('react-bootstrap-table-editing-cell', className) }
|
||||
style={ style }
|
||||
onClick={ this.handleClick }
|
||||
>
|
||||
<TextEditor
|
||||
ref={ node => this.editor = node }
|
||||
|
||||
@ -61,13 +61,18 @@ class CellEditWrapper extends Component {
|
||||
}
|
||||
|
||||
startEditing(ridx, cidx) {
|
||||
this.setState(() => {
|
||||
return {
|
||||
ridx,
|
||||
cidx,
|
||||
editing: true
|
||||
};
|
||||
});
|
||||
const editing = () => {
|
||||
this.setState(() => {
|
||||
return {
|
||||
ridx,
|
||||
cidx,
|
||||
editing: true
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const { selectRow } = this.props;
|
||||
if (!selectRow || (selectRow.clickToEdit || !selectRow.clickToSelect)) editing();
|
||||
}
|
||||
|
||||
escapeEditing() {
|
||||
|
||||
3
packages/react-bootstrap-table2/src/const.js
vendored
3
packages/react-bootstrap-table2/src/const.js
vendored
@ -10,5 +10,6 @@ export default {
|
||||
ROW_SELECT_DISABLED: 'ROW_SELECT_DISABLED',
|
||||
CHECKBOX_STATUS_CHECKED: 'checked',
|
||||
CHECKBOX_STATUS_INDETERMINATE: 'indeterminate',
|
||||
CHECKBOX_STATUS_UNCHECKED: 'unchecked'
|
||||
CHECKBOX_STATUS_UNCHECKED: 'unchecked',
|
||||
DELAY_FOR_DBCLICK: 200
|
||||
};
|
||||
|
||||
192
packages/react-bootstrap-table2/src/row.js
vendored
192
packages/react-bootstrap-table2/src/row.js
vendored
@ -1,5 +1,5 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import _ from './utils';
|
||||
@ -8,91 +8,133 @@ import SelectionCell from './row-selection/selection-cell';
|
||||
import EditingCell from './cell-edit/editing-cell';
|
||||
import Const from './const';
|
||||
|
||||
const Row = (props) => {
|
||||
const {
|
||||
row,
|
||||
columns,
|
||||
keyField,
|
||||
rowIndex,
|
||||
className,
|
||||
style,
|
||||
cellEdit,
|
||||
selected,
|
||||
selectRow,
|
||||
editable: editableRow
|
||||
} = props;
|
||||
class Row extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.clickNum = 0;
|
||||
this.handleRowClick = this.handleRowClick.bind(this);
|
||||
}
|
||||
|
||||
const {
|
||||
mode,
|
||||
onStart,
|
||||
ridx: editingRowIdx,
|
||||
cidx: editingColIdx,
|
||||
...rest
|
||||
} = cellEdit;
|
||||
|
||||
const key = _.get(row, keyField);
|
||||
const { nonSelectable } = selectRow;
|
||||
|
||||
return (
|
||||
<tr style={ style } className={ className }>
|
||||
{
|
||||
selectRow.mode === Const.ROW_SELECT_DISABLED
|
||||
? null
|
||||
: (
|
||||
<SelectionCell
|
||||
{ ...selectRow }
|
||||
rowKey={ _.get(row, keyField) }
|
||||
selected={ selected }
|
||||
disabled={ nonSelectable && nonSelectable.includes(key) }
|
||||
/>
|
||||
)
|
||||
handleRowClick() {
|
||||
const {
|
||||
row,
|
||||
selected,
|
||||
keyField,
|
||||
selectable,
|
||||
selectRow: {
|
||||
onRowSelect,
|
||||
clickToEdit
|
||||
}
|
||||
{
|
||||
columns.map((column, index) => {
|
||||
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);
|
||||
} = this.props;
|
||||
const key = _.get(row, keyField);
|
||||
if (selectable) {
|
||||
const { cellEdit: { mode } } = this.props;
|
||||
if (mode === Const.DBCLICK_TO_CELL_EDIT && clickToEdit) {
|
||||
this.clickNum += 1;
|
||||
_.debounce(() => {
|
||||
if (this.clickNum === 1) {
|
||||
onRowSelect(key, !selected);
|
||||
}
|
||||
if (rowIndex === editingRowIdx && index === editingColIdx) {
|
||||
let editCellstyle = column.editCellStyle || {};
|
||||
let editCellclasses = column.editCellClasses;
|
||||
if (_.isFunction(column.editCellStyle)) {
|
||||
editCellstyle = column.editCellStyle(content, row, rowIndex, index);
|
||||
this.clickNum = 0;
|
||||
}, Const.DELAY_FOR_DBCLICK)();
|
||||
} else {
|
||||
onRowSelect(key, !selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
row,
|
||||
columns,
|
||||
keyField,
|
||||
rowIndex,
|
||||
className,
|
||||
style,
|
||||
cellEdit,
|
||||
selected,
|
||||
selectRow,
|
||||
selectable,
|
||||
editable: editableRow
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
mode,
|
||||
onStart,
|
||||
ridx: editingRowIdx,
|
||||
cidx: editingColIdx,
|
||||
...rest
|
||||
} = cellEdit;
|
||||
|
||||
const key = _.get(row, keyField);
|
||||
const { clickToSelect } = selectRow;
|
||||
|
||||
const trAttrs = {};
|
||||
if (clickToSelect) {
|
||||
trAttrs.onClick = this.handleRowClick;
|
||||
}
|
||||
|
||||
return (
|
||||
<tr style={ style } className={ className } { ...trAttrs }>
|
||||
{
|
||||
selectRow.mode === Const.ROW_SELECT_DISABLED
|
||||
? null
|
||||
: (
|
||||
<SelectionCell
|
||||
{ ...selectRow }
|
||||
rowKey={ key }
|
||||
selected={ selected }
|
||||
disabled={ !selectable }
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
columns.map((column, index) => {
|
||||
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 (_.isFunction(column.editCellClasses)) {
|
||||
editCellclasses = column.editCellClasses(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 }
|
||||
row={ row }
|
||||
column={ column }
|
||||
className={ editCellclasses }
|
||||
style={ editCellstyle }
|
||||
{ ...rest }
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<EditingCell
|
||||
<Cell
|
||||
key={ content }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ index }
|
||||
column={ column }
|
||||
className={ editCellclasses }
|
||||
style={ editCellstyle }
|
||||
{ ...rest }
|
||||
editMode={ mode }
|
||||
editable={ editable }
|
||||
onStart={ onStart }
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Cell
|
||||
key={ content }
|
||||
row={ row }
|
||||
rowIndex={ rowIndex }
|
||||
columnIndex={ index }
|
||||
column={ column }
|
||||
editMode={ mode }
|
||||
editable={ editable }
|
||||
onStart={ onStart }
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
})
|
||||
}
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
row: PropTypes.object.isRequired,
|
||||
|
||||
27
packages/react-bootstrap-table2/src/utils.js
vendored
27
packages/react-bootstrap-table2/src/utils.js
vendored
@ -1,5 +1,6 @@
|
||||
/* eslint no-empty: 0 */
|
||||
/* eslint no-param-reassign: 0 */
|
||||
/* eslint prefer-rest-params: 0 */
|
||||
|
||||
function splitNested(str) {
|
||||
return [str]
|
||||
@ -72,6 +73,29 @@ function sleep(fn, ms) {
|
||||
return setTimeout(() => fn(), ms);
|
||||
}
|
||||
|
||||
function debounce(func, wait, immediate) {
|
||||
let timeout;
|
||||
|
||||
return () => {
|
||||
const later = () => {
|
||||
timeout = null;
|
||||
|
||||
if (!immediate) {
|
||||
func.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
const callNow = immediate && !timeout;
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait || 0);
|
||||
|
||||
if (callNow) {
|
||||
func.appy(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
get,
|
||||
set,
|
||||
@ -79,5 +103,6 @@ export default {
|
||||
isObject,
|
||||
isEmptyObject,
|
||||
isDefined,
|
||||
sleep
|
||||
sleep,
|
||||
debounce
|
||||
};
|
||||
|
||||
@ -349,6 +349,30 @@ describe('Body', () => {
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selectRow.mode is ROW_SELECT_DISABLED (row was un-selectable)', () => {
|
||||
|
||||
@ -146,14 +146,61 @@ describe('CellEditWrapper', () => {
|
||||
});
|
||||
|
||||
describe('call startEditing function', () => {
|
||||
const ridx = 1;
|
||||
const cidx = 3;
|
||||
it('should set state correctly', () => {
|
||||
const ridx = 1;
|
||||
const cidx = 3;
|
||||
wrapper.instance().startEditing(ridx, cidx);
|
||||
expect(wrapper.state().ridx).toEqual(ridx);
|
||||
expect(wrapper.state().cidx).toEqual(cidx);
|
||||
expect(wrapper.state().editing).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('if selectRow.clickToSelect is defined', () => {
|
||||
beforeEach(() => {
|
||||
const selectRow = { mode: 'checkbox', clickToSelect: true };
|
||||
wrapper = shallow(
|
||||
<CellEditWrapper
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
selectRow={ selectRow }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should not set state', () => {
|
||||
wrapper.instance().startEditing(ridx, cidx);
|
||||
expect(wrapper.state().ridx).toBeNull();
|
||||
expect(wrapper.state().cidx).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.clickToSelect and selectRow.clickToEdit is defined', () => {
|
||||
beforeEach(() => {
|
||||
const selectRow = { mode: 'checkbox', clickToSelect: true, clickToEdit: true };
|
||||
wrapper = shallow(
|
||||
<CellEditWrapper
|
||||
keyField={ keyField }
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
cellEdit={ cellEdit }
|
||||
selectRow={ selectRow }
|
||||
store={ store }
|
||||
onUpdateCell={ sinon.stub() }
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
it('should set state correctly', () => {
|
||||
wrapper.instance().startEditing(ridx, cidx);
|
||||
expect(wrapper.state().ridx).toEqual(ridx);
|
||||
expect(wrapper.state().cidx).toEqual(cidx);
|
||||
expect(wrapper.state().editing).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('call completeEditing function', () => {
|
||||
|
||||
@ -37,6 +37,7 @@ describe('Row', () => {
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
@ -470,6 +471,7 @@ describe('Row', () => {
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
selected
|
||||
selectable
|
||||
/>);
|
||||
});
|
||||
|
||||
@ -483,9 +485,8 @@ describe('Row', () => {
|
||||
expect(wrapper.find(SelectionCell).props().mode).toEqual(selectRow.mode);
|
||||
});
|
||||
|
||||
describe('if selectRow.nonSelectable is defined and contain a rowkey which is match to current row', () => {
|
||||
describe('if selectable prop is false', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', nonSelectable: [row.id] };
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
@ -494,6 +495,7 @@ describe('Row', () => {
|
||||
row={ row }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
selectable={ false }
|
||||
/>);
|
||||
});
|
||||
|
||||
@ -503,9 +505,8 @@ describe('Row', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.nonSelectable is defined and not contain any rowkey which is match to current row', () => {
|
||||
describe('if selectable prop is true', () => {
|
||||
beforeEach(() => {
|
||||
selectRow = { mode: 'checkbox', nonSelectable: [3, 4, 6] };
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
@ -514,6 +515,7 @@ describe('Row', () => {
|
||||
row={ row }
|
||||
keyField={ keyField }
|
||||
selectRow={ selectRow }
|
||||
selectable
|
||||
/>);
|
||||
});
|
||||
|
||||
@ -522,5 +524,157 @@ describe('Row', () => {
|
||||
expect(wrapper.find(SelectionCell).prop('disabled')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if selectRow.clickToSelect is true', () => {
|
||||
beforeEach(() => {
|
||||
selectRow.clickToSelect = true;
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
selected
|
||||
selectable
|
||||
/>);
|
||||
});
|
||||
|
||||
it('should render Row component successfully with onClick event', () => {
|
||||
expect(wrapper.length).toBe(1);
|
||||
expect(wrapper.find('tr').prop('onClick')).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleRowClick', () => {
|
||||
let selectRow;
|
||||
let onRowSelectCallBack;
|
||||
|
||||
describe('selectable prop is false', () => {
|
||||
beforeEach(() => {
|
||||
onRowSelectCallBack = sinon.stub();
|
||||
selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
onRowSelect: onRowSelectCallBack
|
||||
};
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
selected
|
||||
selectable={ false }
|
||||
/>);
|
||||
wrapper.find('tr').simulate('click');
|
||||
});
|
||||
|
||||
it('should not calling selectRow.onRowSelect callback', () => {
|
||||
expect(onRowSelectCallBack.callCount).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectable prop is true', () => {
|
||||
describe('and selected prop is true', () => {
|
||||
beforeEach(() => {
|
||||
onRowSelectCallBack = sinon.stub();
|
||||
selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
onRowSelect: onRowSelectCallBack
|
||||
};
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
selected
|
||||
selectable
|
||||
/>);
|
||||
wrapper.find('tr').simulate('click');
|
||||
});
|
||||
|
||||
it('should calling selectRow.onRowSelect callback', () => {
|
||||
expect(onRowSelectCallBack.callCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('should calling selectRow.onRowSelect with correct argument', () => {
|
||||
expect(onRowSelectCallBack.calledWith(row[keyField], false)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('and selected prop is false', () => {
|
||||
beforeEach(() => {
|
||||
onRowSelectCallBack = sinon.stub();
|
||||
selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
onRowSelect: onRowSelectCallBack
|
||||
};
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
selected={ false }
|
||||
selectable
|
||||
/>);
|
||||
wrapper.find('tr').simulate('click');
|
||||
});
|
||||
|
||||
it('should calling selectRow.onRowSelect callback', () => {
|
||||
expect(onRowSelectCallBack.callCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('should calling selectRow.onRowSelect with correct argument', () => {
|
||||
expect(onRowSelectCallBack.calledWith(row[keyField], true)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if cellEdit.mode is dbclick and selectRow.clickToEdit is true', () => {
|
||||
beforeEach(() => {
|
||||
onRowSelectCallBack = sinon.stub();
|
||||
const cellEdit = {
|
||||
mode: Const.DBCLICK_TO_CELL_EDIT,
|
||||
ridx: undefined,
|
||||
cidx: undefined,
|
||||
onStart: sinon.stub()
|
||||
};
|
||||
selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true,
|
||||
clickToEdit: true,
|
||||
onRowSelect: onRowSelectCallBack
|
||||
};
|
||||
wrapper = shallow(
|
||||
<Row
|
||||
{ ...mockBodyResolvedProps }
|
||||
keyField={ keyField }
|
||||
rowIndex={ rowIndex }
|
||||
columns={ defaultColumns }
|
||||
row={ row }
|
||||
selectRow={ selectRow }
|
||||
cellEdit={ cellEdit }
|
||||
selected
|
||||
selectable
|
||||
/>);
|
||||
wrapper.instance().handleRowClick();
|
||||
wrapper.instance().handleRowClick();
|
||||
});
|
||||
|
||||
it('should increase clickNum as 2', () => {
|
||||
expect(wrapper.instance().clickNum).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user