diff --git a/docs/columns.md b/docs/columns.md
index dc1e378..f465c3b 100644
--- a/docs/columns.md
+++ b/docs/columns.md
@@ -417,9 +417,20 @@ A new `Object` will be the result of element headerAttrs.
> Same as [column.attrs](#attrs), it has lower priority and will be
> overwrited when other props related to HTML attributes were given.
-## column.editable - [Bool]
+## column.editable - [Bool | Function]
`column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`.
+If a callback function given, you can control the editable level as cell level:
+
+```js
+{
+ // omit...
+ editable: (cell, row, rowIndex, colIndex) => {
+ // return true or false;
+ }
+}
+```
+
## column.validator - [Function]
`column.validator` used for validate the data when cell on updating. it's should accept a callback function with following argument:
`newValue`, `row` and `column`:
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 605d5d8..26f7136 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -94,6 +94,6 @@ storiesOf('Cell Editing', module)
.add('Blur to Save Cell', () => )
.add('Row Level Editable', () => )
.add('Column Level Editable', () => )
+ .add('Cell Level Editable', () => )
.add('Rich Hook Functions', () => )
- .add('Validation', () => )
- .add('Cell Level Editable', () => );
+ .add('Validation', () => );
diff --git a/packages/react-bootstrap-table2/src/cell.js b/packages/react-bootstrap-table2/src/cell.js
index d9e3582..add0f58 100644
--- a/packages/react-bootstrap-table2/src/cell.js
+++ b/packages/react-bootstrap-table2/src/cell.js
@@ -60,14 +60,6 @@ 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;
}
@@ -94,7 +86,11 @@ class Cell extends Component {
if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle;
if (editable && editMode !== Const.UNABLE_TO_CELL_EDIT) {
- setEditMode();
+ if (editMode === Const.CLICK_TO_CELL_EDIT) {
+ cellAttrs.onClick = this.handleEditingCell;
+ } else {
+ cellAttrs.onDoubleClick = this.handleEditingCell;
+ }
}
return (
{ content } |
diff --git a/packages/react-bootstrap-table2/test/editing-cell.test.js b/packages/react-bootstrap-table2/test/editing-cell.test.js
index 565d6a1..864b7c4 100644
--- a/packages/react-bootstrap-table2/test/editing-cell.test.js
+++ b/packages/react-bootstrap-table2/test/editing-cell.test.js
@@ -4,13 +4,9 @@ import sinon from 'sinon';
import { shallow, mount } from 'enzyme';
import { TableRowWrapper } from './test-helpers/table-wrapper';
-import BootstrapTable from '../src/bootstrap-table';
import EditingCell from '../src/editing-cell';
import TextEditor from '../src/text-editor';
import EditorIndicator from '../src/editor-indicator';
-import { productsGenerator } from './test-helpers/productGenerator';
-import Row from '../src/row';
-import Cell from '../src/cell';
describe('EditingCell', () => {
let wrapper;
@@ -173,34 +169,4 @@ 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/row.test.js b/packages/react-bootstrap-table2/test/row.test.js
index 84e54c3..dd46177 100644
--- a/packages/react-bootstrap-table2/test/row.test.js
+++ b/packages/react-bootstrap-table2/test/row.test.js
@@ -86,7 +86,7 @@ describe('Row', () => {
}
});
- describe('when have column.editable defined false', () => {
+ describe('and column.editable defined false', () => {
const nonEditableColIndex = 1;
beforeEach(() => {
columns[nonEditableColIndex].editable = false;
@@ -101,7 +101,7 @@ describe('Row', () => {
);
});
- it('Cell component should receive correct editMode props', () => {
+ it('Cell component should receive correct editable props', () => {
expect(wrapper.length).toBe(1);
for (let i = 0; i < columns.length; i += 1) {
const column = columns[i];
@@ -114,6 +114,79 @@ describe('Row', () => {
});
});
+ describe('and column.editable defined as function', () => {
+ const nonEditableColIndex = 1;
+ let editableCallBack;
+
+ afterEach(() => {
+ editableCallBack.reset();
+ });
+
+ describe('which return false', () => {
+ beforeEach(() => {
+ editableCallBack = sinon.stub().returns(false);
+ columns[nonEditableColIndex].editable = editableCallBack;
+ wrapper = shallow(
+
+ );
+ });
+
+ it('column.editable callback function should be called once', () => {
+ expect(editableCallBack.callCount).toBe(1);
+ });
+
+ it('Cell component should receive correct editable props', () => {
+ expect(wrapper.length).toBe(1);
+ for (let i = 0; i < columns.length; i += 1) {
+ const column = columns[i];
+ if (i === nonEditableColIndex || column.dataField === keyField) {
+ expect(wrapper.find(Cell).get(i).props.editable).toBeFalsy();
+ } else {
+ expect(wrapper.find(Cell).get(i).props.editable).toBeTruthy();
+ }
+ }
+ });
+ });
+
+ describe('which return true', () => {
+ beforeEach(() => {
+ editableCallBack = sinon.stub().returns(true);
+ columns[nonEditableColIndex].editable = editableCallBack;
+ wrapper = shallow(
+
+ );
+ });
+
+ it('column.editable callback function should be called once', () => {
+ expect(editableCallBack.callCount).toBe(1);
+ });
+
+ it('Cell component should receive correct editable props', () => {
+ expect(wrapper.length).toBe(1);
+ for (let i = 0; i < columns.length; i += 1) {
+ const column = columns[i];
+ if (column.dataField === keyField) {
+ expect(wrapper.find(Cell).get(i).props.editable).toBeFalsy();
+ } else {
+ expect(wrapper.find(Cell).get(i).props.editable).toBeTruthy();
+ }
+ }
+ });
+ });
+ });
+
// Means user defined cellEdit.nonEditableRows
// and some rows will be treated as noneditable by this rules
describe('when editable prop is false', () => {
diff --git a/packages/react-bootstrap-table2/test/test-helpers/productGenerator.js b/packages/react-bootstrap-table2/test/test-helpers/product-generator.js
similarity index 100%
rename from packages/react-bootstrap-table2/test/test-helpers/productGenerator.js
rename to packages/react-bootstrap-table2/test/test-helpers/product-generator.js