From 97e8007ee5ba39ff27ecc12c0abe97b0d9cdd887 Mon Sep 17 00:00:00 2001 From: Abhi Rao Date: Thu, 23 Jun 2016 16:11:42 -0500 Subject: [PATCH 1/2] Adding ability to provide custom editors - On a column you can specify customEditor - pass in a react component class --- .../js/cell-edit/custom-cell-edit-table.js | 146 ++++++++++++++++++ examples/js/cell-edit/demo.js | 10 ++ src/BootstrapTable.js | 1 + src/TableBody.js | 6 +- src/TableEditColumn.js | 21 ++- 5 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 examples/js/cell-edit/custom-cell-edit-table.js diff --git a/examples/js/cell-edit/custom-cell-edit-table.js b/examples/js/cell-edit/custom-cell-edit-table.js new file mode 100644 index 000000000..04ec16c2e --- /dev/null +++ b/examples/js/cell-edit/custom-cell-edit-table.js @@ -0,0 +1,146 @@ +/* eslint max-len: 0 */ +/* eslint no-alert: 0 */ +/* eslint guard-for-in: 0 */ +/* eslint no-unused-vars: 0 */ +import React from 'react'; +import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table'; + + +const products = []; + +const currencies = [ 'USD', 'GBP', 'EUR' ]; +const regions = [ 'North', 'South', 'East', 'West' ]; + +function addProducts(quantity) { + const startId = products.length; + for (let i = 0; i < quantity; i++) { + const id = startId + i; + products.push({ + id: id, + name: 'Item name ' + id, + price: { + amount: 2100 + i, + currency: currencies[i % currencies.length] + }, + regions: regions.slice(0, (i % regions.length) + 1) + }); + } +} + +addProducts(5); + +const cellEditProp = { + mode: 'click' +}; + +class PriceEditor extends React.Component { + constructor(props) { + super(props); + this.updateData = this.updateData.bind(this); + this.state = { amount: props.defaultValue.amount, currency: props.defaultValue.currency }; + } + focus() { + this.refs.inputRef.focus(); + } + updateData() { + this.props.onUpdate({ amount: this.state.amount, currency: this.state.currency }); + } + render() { + return ( + + { this.setState({ amount: parseInt(ev.currentTarget.value, 10) }); } } /> + + + + ); + } +} + +class RegionsEditor extends React.Component { + constructor(props) { + super(props); + this.updateData = this.updateData.bind(this); + this.state = { regions: props.defaultValue }; + this.onToggleRegion = this.onToggleRegion.bind(this); + } + focus() { + } + onToggleRegion(event) { + const region = event.currentTarget.name; + if (this.state.regions.indexOf(region) < 0) { + this.setState({ regions: this.state.regions.concat([ region ]) }); + } else { + this.setState({ regions: this.state.regions.filter(r => r !== region) }); + } + } + updateData() { + this.props.onUpdate(this.state.regions); + } + render() { + const regionCheckBoxes = regions.map(region => ( + + -1 } + onChange={ this.onToggleRegion } /> + + + )); + return ( + + { regionCheckBoxes } + + + ); + } +} + +function priceFormatter(cell, row) { + return ` ${cell.amount}`; +} + +const regionsFormatter = (cell, row) => ({ (cell || []).join(',') }); + +export default class CustomCellEditTable extends React.Component { + render() { + return ( + + Product ID + Product Name + + Product Price + + + Regions + + + ); + } +} diff --git a/examples/js/cell-edit/demo.js b/examples/js/cell-edit/demo.js index 22611e98a..7d2eff9fc 100644 --- a/examples/js/cell-edit/demo.js +++ b/examples/js/cell-edit/demo.js @@ -5,6 +5,7 @@ import DbClickToEditTable from './dbclick-to-edit-table'; import BlurToSaveTable from './blur-to-save-table'; import CellEditHookTable from './cell-edit-hook-table'; import NonEditableTable from './non-editable-table'; +import CustomCellEditTable from './custom-cell-edit-table'; class Demo extends React.Component { render() { @@ -59,6 +60,15 @@ class Demo extends React.Component { +
+
+
Custom Cell Editor Example
+
+
Source in /examples/js/cell-edit/custom-cell-edit-table.js
+ +
+
+
); } diff --git a/src/BootstrapTable.js b/src/BootstrapTable.js index b422cc7fe..cb5187a89 100644 --- a/src/BootstrapTable.js +++ b/src/BootstrapTable.js @@ -124,6 +124,7 @@ class BootstrapTable extends Component { formatExtraData: column.props.formatExtraData, filterFormatted: column.props.filterFormatted, editable: column.props.editable, + customEditor: column.props.customEditor, hidden: column.props.hidden, hiddenOnInsert: column.props.hiddenOnInsert, searchable: column.props.searchable, diff --git a/src/TableBody.js b/src/TableBody.js index 6467f1cbc..844d818cb 100644 --- a/src/TableBody.js +++ b/src/TableBody.js @@ -52,13 +52,13 @@ class TableBody extends Component { completeEdit={ this.handleCompleteEditCell } // add by bluespring for column editor customize editable={ editable } + customEditor={ column.customEditor } format={ column.format ? format : false } key={ i } blurToSave={ this.props.cellEdit.blurToSave } rowIndex={ r } - colIndex={ i }> - { fieldValue } - + colIndex={ i } + fieldValue={ fieldValue } /> ); } else { // add by bluespring for className customize diff --git a/src/TableEditColumn.js b/src/TableEditColumn.js index 13803eddb..e2c75bff2 100644 --- a/src/TableEditColumn.js +++ b/src/TableEditColumn.js @@ -48,6 +48,10 @@ class TableEditColumn extends Component { } } + handleCustomUpdate = value => { + this.props.completeEdit(value, this.props.rowIndex, this.props.colIndex); + } + validator(value) { const ts = this; if (ts.props.editable.validator) { @@ -82,7 +86,7 @@ class TableEditColumn extends Component { } render() { - const { editable, format, children } = this.props; + const { editable, format, fieldValue, customEditor } = this.props; const { shakeEditor } = this.state; const attr = { ref: 'inputRef', @@ -93,9 +97,15 @@ class TableEditColumn extends Component { editable.placeholder && (attr.placeholder = editable.placeholder); const editorClass = classSet({ 'animated': shakeEditor, 'shake': shakeEditor }); + const CustomEditor = customEditor; + const cellEditor = CustomEditor ? : + editor(editable, attr, format, editorClass, fieldValue || ''); return ( - { editor(editable, attr, format, editorClass, children || '') } + { cellEditor } ); @@ -116,7 +126,12 @@ TableEditColumn.propTypes = { blurToSave: PropTypes.bool, editable: PropTypes.oneOfType([ PropTypes.bool, PropTypes.object ]), format: PropTypes.oneOfType([ PropTypes.bool, PropTypes.func ]), - children: PropTypes.node + fieldValue: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.bool, + PropTypes.number, + PropTypes.object + ]) }; From b162b526fcffab6edd455ed2727fb69b79da8635 Mon Sep 17 00:00:00 2001 From: Abhi Rao Date: Fri, 15 Jul 2016 17:20:00 -0500 Subject: [PATCH 2/2] Updating Custom Cell Editing - matching interface of custom filters - Need to pass in a factory method and custom properties --- .../js/cell-edit/custom-cell-edit-table.js | 8 +++++--- src/TableEditColumn.js | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/js/cell-edit/custom-cell-edit-table.js b/examples/js/cell-edit/custom-cell-edit-table.js index 04ec16c2e..d645136eb 100644 --- a/examples/js/cell-edit/custom-cell-edit-table.js +++ b/examples/js/cell-edit/custom-cell-edit-table.js @@ -50,7 +50,6 @@ class PriceEditor extends React.Component { ({ (cell || []).join(',') }); +const createPriceEditor = (onUpdate, props) => (); +const createRegionsEditor = (onUpdate, props) => (); + export default class CustomCellEditTable extends React.Component { render() { return ( @@ -131,13 +133,13 @@ export default class CustomCellEditTable extends React.Component { + customEditor={ { getElement: createPriceEditor, customEditorParameters: { currencies: currencies } } }> Product Price + customEditor={ { getElement: createRegionsEditor } }> Regions diff --git a/src/TableEditColumn.js b/src/TableEditColumn.js index e2c75bff2..5848e4483 100644 --- a/src/TableEditColumn.js +++ b/src/TableEditColumn.js @@ -97,12 +97,18 @@ class TableEditColumn extends Component { editable.placeholder && (attr.placeholder = editable.placeholder); const editorClass = classSet({ 'animated': shakeEditor, 'shake': shakeEditor }); - const CustomEditor = customEditor; - const cellEditor = CustomEditor ? : - editor(editable, attr, format, editorClass, fieldValue || ''); + let cellEditor; + if (customEditor) { + const customEditorProps = { + ...attr, + defaultValue: fieldValue || '', + ...customEditor.customEditorParameters + }; + cellEditor = customEditor.getElement(this.handleCustomUpdate, customEditorProps); + } else { + cellEditor = editor(editable, attr, format, editorClass, fieldValue || ''); + } + return ( { cellEditor } @@ -130,6 +136,7 @@ TableEditColumn.propTypes = { PropTypes.string, PropTypes.bool, PropTypes.number, + PropTypes.array, PropTypes.object ]) };