From 7760d6a7f8770976a1560ae3a1f7953ead60fb43 Mon Sep 17 00:00:00 2001 From: Allen Date: Tue, 10 Oct 2017 02:03:00 -0500 Subject: [PATCH] refine #71 * refine #71 * patch docs for column.editable --- docs/columns.md | 13 +++- .../stories/index.js | 4 +- packages/react-bootstrap-table2/src/cell.js | 14 ++-- .../test/editing-cell.test.js | 34 -------- .../react-bootstrap-table2/test/row.test.js | 77 ++++++++++++++++++- ...oductGenerator.js => product-generator.js} | 0 6 files changed, 94 insertions(+), 48 deletions(-) rename packages/react-bootstrap-table2/test/test-helpers/{productGenerator.js => product-generator.js} (100%) 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