From ad7d31cd3978eb45da7c6194dbab93c1e9a8594d Mon Sep 17 00:00:00 2001 From: Miha Valencic Date: Sat, 6 May 2017 18:33:17 +0200 Subject: [PATCH] Add column id to the rowInfo object (#253) * Add column id to the rowInfo object (passed to render). Resolves #237 * Creating a new object instead of modifying existing rowInfo; Refs #253 * Code style compliance. Refs #253 --- .storybook/config.js | 2 + README.md | 7 ++- src/index.js | 27 +++++---- stories/EditableTable.js | 124 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+), 16 deletions(-) create mode 100644 stories/EditableTable.js diff --git a/.storybook/config.js b/.storybook/config.js index b064361..51302d8 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -27,6 +27,7 @@ import Footers from '../stories/Footers.js' import Filtering from '../stories/Filtering.js' import ControlledTable from '../stories/ControlledTable.js' import PivotingOptions from '../stories/PivotingOptions.js' +import EditableTable from '../stories/EditableTable.js' // configure(() => { storiesOf('1. Docs') @@ -59,4 +60,5 @@ configure(() => { .add('Footers', Footers) .add('Custom Filtering', Filtering) .add('Controlled Component', ControlledTable) + .add('Editable table', EditableTable) }, module) diff --git a/README.md b/README.md index e330759..043ab96 100644 --- a/README.md +++ b/README.md @@ -330,10 +330,11 @@ Or just define them as props // Cell Options className: '', // Set the classname of the `td` element of the column style: {}, // Set the style of the `td` element of the column - render: JSX eg. (rowInfo: {value, rowValues, row, index, viewIndex}) => {value}, // Provide a JSX element or stateless function to render whatever you want as the column's cell with access to the entire row + render: JSX eg. (cellInfo: {value, rowValues, row, column, index, viewIndex}) => {value}, // Provide a JSX element or stateless function to render whatever you want as the column's cell with access to the entire row // value == the accessed value of the column // rowValues == an object of all of the accessed values for the row // row == the original row of data supplied to the table + // column == the column properties (id, header, sortable, ...) // index == the original index of the data supplied to the table // viewIndex == the index of the row in the current page @@ -482,8 +483,8 @@ Every single built-in component's props can be dynamically extended using any on getTdProps={fn} getPaginationProps={fn} getLoadingProps={fn} - getNoDataProps: {fn}, - getResizerProps: {fn} + getNoDataProps={fn} + getResizerProps={fn} /> ``` diff --git a/src/index.js b/src/index.js index e7061e2..77a272e 100644 --- a/src/index.js +++ b/src/index.js @@ -460,6 +460,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { {...trProps.rest} > {allVisibleColumns.map((column, i2) => { + const cellInfo = { ...rowInfo, column: {...column} } const resized = resizing.find(x => x.id === column.id) || {} const show = typeof column.show === 'function' ? column.show() : column.show const width = _.getFirstDefined(resized.value, column.width, column.minWidth) @@ -484,16 +485,16 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { if (column.expander) { const onTdClick = (e) => { if (onExpandRow) { - return onExpandRow(rowInfo.nestingPath, e) + return onExpandRow(cellInfo.nestingPath, e) } let newExpandedRows = _.clone(expandedRows) if (isExpanded) { return this.setStateWithData({ - expandedRows: _.set(newExpandedRows, rowInfo.nestingPath, false) + expandedRows: _.set(newExpandedRows, cellInfo.nestingPath, false) }) } return this.setStateWithData({ - expandedRows: _.set(newExpandedRows, rowInfo.nestingPath, {}) + expandedRows: _.set(newExpandedRows, cellInfo.nestingPath, {}) }) } @@ -523,7 +524,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { )} style={{ ...styles, - paddingLeft: rowInfo.nestingPath.length === 1 ? undefined : `${30 * (rowInfo.nestingPath.length - 1)}px`, + paddingLeft: rowInfo.nestingPath.length === 1 ? undefined : `${30 * (cellInfo.nestingPath.length - 1)}px`, flex: `${pivotFlex} 0 auto`, width: `${pivotWidth}px`, maxWidth: `${pivotMaxWidth}px` @@ -531,18 +532,18 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { {...tdProps.rest} onClick={onTdClick} > - {rowInfo.subRows ? ( + {cellInfo.subRows ? ( _.normalizeComponent(column.render, { - ...rowInfo, + ...cellInfo, value: row[pivotValKey], isExpanded - }, rowInfo.rowValues[column.id]) + }, cellInfo.rowValues[column.id]) ) : SubComponent ? ( _.normalizeComponent(column.render, { - ...rowInfo, - value: rowInfo.rowValues[column.id], + ...cellInfo, + value: cellInfo.rowValues[column.id], isExpanded - }, rowInfo.rowValues[column.id]) + }, cellInfo.rowValues[column.id]) ) : null} ) @@ -567,10 +568,10 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { {...extraProps} > {_.normalizeComponent(column.render, { - ...rowInfo, - value: rowInfo.rowValues[column.id], + ...cellInfo, + value: cellInfo.rowValues[column.id], isExpanded - }, rowInfo.rowValues[column.id])} + }, cellInfo.rowValues[column.id])} ) })} diff --git a/stories/EditableTable.js b/stories/EditableTable.js new file mode 100644 index 0000000..5634568 --- /dev/null +++ b/stories/EditableTable.js @@ -0,0 +1,124 @@ +import React from 'react' +import _ from 'lodash' +import namor from 'namor' + +import CodeHighlight from './components/codeHighlight' +import ReactTable from '../src/index' + +class MyTable extends React.Component { + constructor(props, context) { + super(props, context); + this.renderEditable = this.renderEditable.bind(this); + + this.state = { + data: [ + { firstName: 'Lucy', lastName: 'Marks' }, + { firstName: 'Bejamin', lastName: 'Pike' } + ] + }; + + this.columns = [ + { + header: 'First Name', + accessor: 'firstName', + render: this.renderEditable + }, + { + header: 'Last Name', + accessor: 'lastName', + render: this.renderEditable + }, + { + header: 'Full Name', + id: 'full', + accessor: d => d.firstName + ' ' + d.lastName + } + ]; + } + + renderEditable(cellInfo) { + return (
{ + const data = [...this.state.data]; + data[cellInfo.index][cellInfo.column.id] = e.target.textContent; + this.setState({data: data}); + }}>{this.state.data[cellInfo.index][cellInfo.column.id]}
); + } + + render() { + return (); + } +} + +function getCode() { + return ` +class MyTable extends React.Component { + constructor(props, context) { + super(props, context); + this.renderEditable = this.renderEditable.bind(this); + + this.state = { + data: [ + { firstName: 'Lucy', lastName: 'Marks' }, + { firstName: 'Bejamin', lastName: 'Pike' } + ] + }; + + this.columns = [ + { + header: 'First Name', + accessor: 'firstName', + render: this.renderEditable + }, + { + header: 'Last Name', + accessor: 'lastName', + render: this.renderEditable + }, + { + header: 'Full Name', + id: 'full', + accessor: d => d.firstName + ' ' + d.lastName + } + ]; + } + + renderEditable(cellInfo) { + return (
{ + const data = [...this.state.data]; + data[cellInfo.index][cellInfo.column.id] = e.target.textContent; + this.setState({data: data}); + }}>{this.state.data[cellInfo.index][cellInfo.column.id]}
); + } + + render() { + return (); + } +} +` +} + +export default () => { + + return ( +
+

First two columns are editable just by clicking into them using the contentEditable attribute. Last column (Full Name) is computed from the first two.

+
+ +
+ + {() => getCode()} +
+ ) +} \ No newline at end of file