diff --git a/packages/react-bootstrap-table2-example/examples/cell-edit/cell-level-editable-table.js b/packages/react-bootstrap-table2-example/examples/cell-edit/cell-level-editable-table.js
new file mode 100644
index 0000000..da825d1
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/cell-edit/cell-level-editable-table.js
@@ -0,0 +1,55 @@
+/* eslint no-unused-vars: 0 */
+import React from 'react';
+
+import { BootstrapTableful } 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',
+ editable: (content, row, rowIndex, columnIndex) => content > 2101
+}];
+
+const sourceCode = `\
+const columns = [{
+ dataField: 'id',
+ text: 'Product ID'
+}, {
+ dataField: 'name',
+ text: 'Product Name'
+}, {
+ dataField: 'price',
+ text: 'Product Price',
+ editable: (content, row, rowIndex, columnIndex) => content > 2101
+}];
+
+const cellEdit = {
+ mode: 'click'
+};
+
+
+`;
+
+const cellEdit = {
+ mode: 'click'
+};
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 7c43434..605d5d8 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -41,6 +41,7 @@ import DoubleClickToEditTable from 'examples/cell-edit/dbclick-to-edit-table';
import BlurToSaveTable from 'examples/cell-edit/blur-to-save-table';
import RowLevelEditableTable from 'examples/cell-edit/row-level-editable-table';
import ColumnLevelEditableTable from 'examples/cell-edit/column-level-editable-table';
+import CellLevelEditable from 'examples/cell-edit/cell-level-editable-table';
import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table';
import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table';
@@ -94,4 +95,5 @@ storiesOf('Cell Editing', module)
.add('Row Level Editable', () => )
.add('Column Level Editable', () => )
.add('Rich Hook Functions', () => )
- .add('Validation', () => );
+ .add('Validation', () => )
+ .add('Cell Level Editable', () => );
diff --git a/packages/react-bootstrap-table2/src/cell.js b/packages/react-bootstrap-table2/src/cell.js
index e4431e6..d9e3582 100644
--- a/packages/react-bootstrap-table2/src/cell.js
+++ b/packages/react-bootstrap-table2/src/cell.js
@@ -60,6 +60,14 @@ class Cell extends Component {
? classes(content, row, rowIndex, columnIndex)
: classes;
+ const setEditMode = () => {
+ if (editMode === Const.CLICK_TO_CELL_EDIT) {
+ cellAttrs.onClick = this.handleEditingCell;
+ } else {
+ cellAttrs.onDoubleClick = this.handleEditingCell;
+ }
+ };
+
if (style) {
cellStyle = _.isFunction(style) ? style(content, row, rowIndex, columnIndex) : style;
}
@@ -85,13 +93,8 @@ class Cell extends Component {
if (cellClasses) cellAttrs.className = cellClasses;
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
-
if (editable && editMode !== Const.UNABLE_TO_CELL_EDIT) {
- if (editMode === Const.CLICK_TO_CELL_EDIT) { // click to edit
- cellAttrs.onClick = this.handleEditingCell;
- } else { // dbclick to edit
- cellAttrs.onDoubleClick = this.handleEditingCell;
- }
+ setEditMode();
}
return (
{ content } |
diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js
index 1b9c42a..13c6727 100644
--- a/packages/react-bootstrap-table2/src/header-cell.js
+++ b/packages/react-bootstrap-table2/src/header-cell.js
@@ -100,7 +100,7 @@ HeaderCell.propTypes = {
align: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
sort: PropTypes.bool,
sortFunc: PropTypes.func,
- editable: PropTypes.bool,
+ editable: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
validator: PropTypes.func
}).isRequired,
index: PropTypes.number.isRequired,
diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js
index ed76102..117dce4 100644
--- a/packages/react-bootstrap-table2/src/row.js
+++ b/packages/react-bootstrap-table2/src/row.js
@@ -26,12 +26,17 @@ const Row = (props) => {
{
columns.map((column, index) => {
+ const { dataField } = column;
+ const content = _.get(row, dataField);
let editable = _.isDefined(column.editable) ? column.editable : true;
- if (column.dataField === keyField || !editableRow) editable = false;
+ if (dataField === keyField || !editableRow) editable = false;
+ if (_.isFunction(column.editable)) {
+ editable = column.editable(content, row, rowIndex, index);
+ }
if (rowIndex === editingRowIdx && index === editingColIdx) {
return (
{
}
return (
| {
let wrapper;
@@ -170,4 +173,34 @@ describe('EditingCell', () => {
});
});
});
+
+ describe('when column.editable is function', () => {
+ const products = productsGenerator();
+ const mockFunction = jest.fn(content => content > 2102);
+ const col = [{
+ dataField: 'id',
+ text: 'Product ID'
+ }, {
+ dataField: 'name',
+ text: 'Product Name'
+ }, {
+ dataField: 'price',
+ text: 'Product Price',
+ editable: mockFunction
+ }];
+ const renderComponent = mount();
+ const rowComponent = renderComponent.find(Row);
+ it(`column.editable function should be called ${products.length} times`, () => {
+ expect(mockFunction).toHaveBeenCalledTimes(products.length);
+ });
+ it('should call callBack with right args', () => {
+ expect(mockFunction).toHaveBeenLastCalledWith(2104, { id: 4, name: 'Item name 4', price: 2104 }, 4, 2);
+ });
+ it('should be "editable" === false', () => {
+ expect(rowComponent.at(2).find(Cell).at(2).props().editable).toBeFalsy();
+ });
+ it('should be "editable" === true', () => {
+ expect(rowComponent.at(3).find(Cell).at(2).props().editable).toBeTruthy();
+ });
+ });
});
diff --git a/packages/react-bootstrap-table2/test/test-helpers/productGenerator.js b/packages/react-bootstrap-table2/test/test-helpers/productGenerator.js
new file mode 100644
index 0000000..4049e60
--- /dev/null
+++ b/packages/react-bootstrap-table2/test/test-helpers/productGenerator.js
@@ -0,0 +1,21 @@
+/**
+ * products generator for stories
+ *
+ * @param {Number} quantity - quantity of products
+ * @param {Function} callback - callback func which is similiar to 'mapFunction'
+ * aims to customize product format
+ *
+ * @return {Array} - products array
+ */
+export const productsGenerator = (quantity = 5, callback) => {
+ if (callback) return Array.from({ length: quantity }, callback);
+
+ // if no given callback, retrun default product format.
+ return (
+ Array.from({ length: quantity }, (value, index) => ({
+ id: index,
+ name: `Item name ${index}`,
+ price: 2100 + index
+ }))
+ );
+};
|