From 943b580a2bfcf60267e32d20c208a3b45fbfbd45 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Wed, 21 Mar 2018 00:16:07 +0800 Subject: [PATCH] fix #258 --- docs/columns.md | 8 + .../react-bootstrap-table2-editor/README.md | 6 +- .../src/editing-cell.js | 21 ++- .../test/editing-cell.test.js | 141 +++++++++++++++++- .../examples/cell-edit/editor-class-table.js | 61 ++++++++ .../examples/cell-edit/editor-style-table.js | 69 +++++++++ .../stories/index.js | 8 +- .../react-bootstrap-table2/src/header-cell.js | 2 + packages/react-bootstrap-table2/src/row.js | 2 + 9 files changed, 311 insertions(+), 7 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/cell-edit/editor-class-table.js create mode 100644 packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js diff --git a/docs/columns.md b/docs/columns.md index eeab42ba2..d7a7beaf7 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -32,6 +32,8 @@ Available properties in a column object: * [validator](#validator) * [editCellStyle](#editCellStyle) * [editCellClasses](#editCellClasses) +* [editorStyle](#editorStyle) +* [editorClasses](#editorClasses) * [filter](#filter) * [filterValue](#filterValue) @@ -552,6 +554,12 @@ Or take a callback function } ``` +## column.editorStyle - [Object | Function] +This is almost same as [`column.editCellStyle`](#editCellStyle), but `column.editorStyle` is custom the style on editor instead of cell(`td`). + +## column.editorClasses - [Object | Function] +This is almost same as [`column.editCellClasses`](#editCellClasses), but `column.editorClasses` is custom the class on editor instead of cell(`td`). + ## column.filter - [Object] Configure `column.filter` will able to setup a column level filter on the header column. Currently, `react-bootstrap-table2` support following filters: diff --git a/packages/react-bootstrap-table2-editor/README.md b/packages/react-bootstrap-table2-editor/README.md index 02e0e46af..5c9719e1b 100644 --- a/packages/react-bootstrap-table2-editor/README.md +++ b/packages/react-bootstrap-table2-editor/README.md @@ -49,13 +49,15 @@ How user save their new editings? We offer two ways: * Cell Level (Configure [column.editable](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditable-bool-function) as a callback function) ## Customize Style/Class -Currently, we only support the editing cell style/class customization, in the future, we will offer more customizations. - ### Editing Cell * Customize the editing cell style via [column.editCellStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellstyle-object-function) * Customize the editing cell classname via [column.editCellClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellclasses-string-function) +### Editor +* Customize the editor style via [column.editorStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditorstyle-object-function) +* Customize the editor classname via [column.editoClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditorclasses-string-function) + ## Validation [`column.validator`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnvalidator-function) will help you to work on it! \ No newline at end of file diff --git a/packages/react-bootstrap-table2-editor/src/editing-cell.js b/packages/react-bootstrap-table2-editor/src/editing-cell.js index 5e54984c6..2c732de0d 100644 --- a/packages/react-bootstrap-table2-editor/src/editing-cell.js +++ b/packages/react-bootstrap-table2-editor/src/editing-cell.js @@ -14,7 +14,9 @@ export default _ => class EditingCell extends Component { static propTypes = { row: PropTypes.object.isRequired, + rowIndex: PropTypes.number.isRequired, column: PropTypes.object.isRequired, + columnIndex: PropTypes.number.isRequired, onUpdate: PropTypes.func.isRequired, onEscape: PropTypes.func.isRequired, timeToCloseMessage: PropTypes.number, @@ -123,7 +125,7 @@ export default _ => render() { const { invalidMessage } = this.state; - const { row, column, className, style } = this.props; + const { row, column, className, style, rowIndex, columnIndex } = this.props; const { dataField } = column; const value = _.get(row, dataField); @@ -133,7 +135,21 @@ export default _ => }; const hasError = _.isDefined(invalidMessage); - const editorClass = hasError ? cs('animated', 'shake') : null; + let customEditorClass = column.editorClasses || ''; + if (_.isFunction(column.editorClasses)) { + customEditorClass = column.editorClasses(value, row, rowIndex, columnIndex); + } + + let editorStyle = column.editorStyle || {}; + if (_.isFunction(column.editorStyle)) { + editorStyle = column.editorStyle(value, row, rowIndex, columnIndex); + } + + const editorClass = cs({ + animated: hasError, + shake: hasError + }, customEditorClass); + return ( this.editor = node } defaultValue={ value } + style={ editorStyle } className={ editorClass } { ...editorAttrs } /> diff --git a/packages/react-bootstrap-table2-editor/test/editing-cell.test.js b/packages/react-bootstrap-table2-editor/test/editing-cell.test.js index 9b34d9388..2741ee103 100644 --- a/packages/react-bootstrap-table2-editor/test/editing-cell.test.js +++ b/packages/react-bootstrap-table2-editor/test/editing-cell.test.js @@ -28,6 +28,9 @@ describe('EditingCell', () => { name: 'A' }; + const rowIndex = 1; + const columnIndex = 1; + let column = { dataField: 'id', text: 'ID' @@ -39,6 +42,8 @@ describe('EditingCell', () => { wrapper = shallow( { expect(textEditor.props().defaultValue).toEqual(row[column.dataField]); expect(textEditor.props().onKeyDown).toBeDefined(); expect(textEditor.props().onBlur).toBeDefined(); - expect(textEditor.props().className).toBeNull(); + expect(textEditor.props().className).toEqual(''); }); it('should not render EditorIndicator due to state.invalidMessage is null', () => { @@ -92,6 +97,8 @@ describe('EditingCell', () => { wrapper = shallow( { wrapper = shallow( { }); }); + describe('if column.editorClasses is defined', () => { + let columnWithEditorClasses; + const classes = 'test test1'; + + describe('and it is a function', () => { + beforeEach(() => { + columnWithEditorClasses = { + ...column, + editorClasses: jest.fn(() => classes) + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().className).toEqual(classes); + }); + + it('should call column.editorClasses correctly', () => { + expect(columnWithEditorClasses.editorClasses).toHaveBeenCalledTimes(1); + expect(columnWithEditorClasses.editorClasses).toHaveBeenCalledWith( + _.get(row, column.dataField), + row, + rowIndex, + columnIndex + ); + }); + }); + + describe('and it is a string', () => { + beforeEach(() => { + columnWithEditorClasses = { + ...column, + editorClasses: classes + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().className).toEqual(classes); + }); + }); + }); + + describe('if column.editorStyle is defined', () => { + let columnWithEditorStyle; + const style = { color: 'red' }; + + describe('and it is a function', () => { + beforeEach(() => { + columnWithEditorStyle = { + ...column, + editorStyle: jest.fn(() => style) + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().style).toEqual(style); + }); + + it('should call column.editorStyle correctly', () => { + expect(columnWithEditorStyle.editorStyle).toHaveBeenCalledTimes(1); + expect(columnWithEditorStyle.editorStyle).toHaveBeenCalledWith( + _.get(row, column.dataField), + row, + rowIndex, + columnIndex + ); + }); + }); + + describe('and it is an object', () => { + beforeEach(() => { + columnWithEditorStyle = { + ...column, + editorStyle: style + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().style).toEqual(style); + }); + }); + }); + describe('if blurToSave prop is true', () => { beforeEach(() => { wrapper = mount( { wrapper = mount( + (cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101') +}]; + +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', + editorClasses: 'editing-name' +}, { + dataField: 'price', + text: 'Product Price', + editorClasses: (cell, row, rowIndex, colIndex) => + (cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101') +}]; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js b/packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js new file mode 100644 index 000000000..37bf5bf96 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js @@ -0,0 +1,69 @@ +/* eslint no-unused-vars: 0 */ +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', + editorStyle: { + backgroundColor: '#20B2AA' + } +}, { + dataField: 'price', + text: 'Product Price', + editorStyle: (cell, row, rowIndex, colIndex) => { + const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF'; + return { backgroundColor }; + } +}]; + +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', + editorStyle: { + backgroundColor: '#20B2AA' + } +}, { + dataField: 'price', + text: 'Product Price', + editorStyle: (cell, row, rowIndex, colIndex) => { + const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF'; + return { backgroundColor }; + } +}]; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 3f116f508..ae50d60ed 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -73,6 +73,8 @@ 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 EditorStyleTable from 'examples/cell-edit/editor-style-table'; +import EditorClassTable from 'examples/cell-edit/editor-class-table'; // work on row selection import SingleSelectionTable from 'examples/row-selection/single-selection'; @@ -186,8 +188,10 @@ storiesOf('Cell Editing', module) .add('Cell Level Editable', () => ) .add('Rich Hook Functions', () => ) .add('Validation', () => ) - .add('Custom Cell Style When Editing', () => ) - .add('Custom Cell Classes When Editing', () => ); + .add('Custom Cell Style', () => ) + .add('Custom Cell Classes', () => ) + .add('Custom Editor Classes', () => ) + .add('Custom Editor Style', () => ); storiesOf('Row Selection', module) .add('Single Selection', () => ) diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js index bb012d182..69fdfed11 100644 --- a/packages/react-bootstrap-table2/src/header-cell.js +++ b/packages/react-bootstrap-table2/src/header-cell.js @@ -130,6 +130,8 @@ HeaderCell.propTypes = { editable: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]), editCellStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), editCellClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + editorStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), + editorClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), validator: PropTypes.func, filter: PropTypes.object, filterValue: PropTypes.func diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index 3efb0c529..b6222bb07 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -79,7 +79,9 @@ class Row extends eventDelegater(Component) {