diff --git a/plugins/woocommerce-admin/packages/components/CHANGELOG.md b/plugins/woocommerce-admin/packages/components/CHANGELOG.md index ee43dee16f1..accbd7f9e6e 100644 --- a/plugins/woocommerce-admin/packages/components/CHANGELOG.md +++ b/plugins/woocommerce-admin/packages/components/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - Revert Card component removal #7167. +- Add rowKey prop to Table and TableCard component. #7196 # 7.0.0 diff --git a/plugins/woocommerce-admin/packages/components/src/table/README.md b/plugins/woocommerce-admin/packages/components/src/table/README.md index d35a9220ba1..4d2735c2611 100644 --- a/plugins/woocommerce-admin/packages/components/src/table/README.md +++ b/plugins/woocommerce-admin/packages/components/src/table/README.md @@ -76,6 +76,7 @@ Name | Type | Default | Description `title` | String | `null` | (required) The title used in the card header, also used as the caption for the content in this table `totalRows` | Number | `null` | (required) The total number of rows (across all pages) `baseSearchQuery` | Object | `{}` | Pass in query parameters to be included in the path when onSearch creates a new url +`rowKey` | Function(row, index): string | `null` | Function used for the row key. ### `labels` structure @@ -213,6 +214,7 @@ const rows = [ caption="Revenue Last Week" rows={ rows } headers={ headers } + rowKey={ row => row.display } /> ``` @@ -228,6 +230,7 @@ Name | Type | Default | Description `query` | Object | `{}` | The query string represented in object form `rows` | Array | `null` | (required) An array of arrays of display/value object pairs `rowHeader` | One of type: number, bool | `0` | Which column should be the row header, defaults to the first item (`0`) (but could be set to `1`, if the first col is checkboxes, for example). Set to false to disable row headers +`rowKey` | Function(row, index): string | `null` | Function used to get the row key. ### `headers` structure diff --git a/plugins/woocommerce-admin/packages/components/src/table/index.js b/plugins/woocommerce-admin/packages/components/src/table/index.js index 100cf4954d1..27e08ea533f 100644 --- a/plugins/woocommerce-admin/packages/components/src/table/index.js +++ b/plugins/woocommerce-admin/packages/components/src/table/index.js @@ -152,6 +152,7 @@ class TableCard extends Component { summary, title, totalRows, + rowKey, } = this.props; const { showCols } = this.state; const allHeaders = this.props.headers; @@ -238,6 +239,7 @@ class TableCard extends Component { caption={ title } query={ query } onSort={ onSort || onQueryChange( 'sort' ) } + rowKey={ rowKey } /> ) } @@ -350,6 +352,11 @@ TableCard.propTypes = { * The total number of rows (across all pages). */ totalRows: PropTypes.number.isRequired, + /** + * The rowKey used for the key value on each row, this can be a string of the key or a function that returns the value. + * This uses the index if not defined. + */ + rowKey: PropTypes.func, }; TableCard.defaultProps = { diff --git a/plugins/woocommerce-admin/packages/components/src/table/stories/table.js b/plugins/woocommerce-admin/packages/components/src/table/stories/table.js index 74e81d56471..f7a624723a3 100644 --- a/plugins/woocommerce-admin/packages/components/src/table/stories/table.js +++ b/plugins/woocommerce-admin/packages/components/src/table/stories/table.js @@ -11,7 +11,12 @@ import { rows, headers } from './index'; export const Basic = () => ( - +
row[ 0 ].value } + /> ); diff --git a/plugins/woocommerce-admin/packages/components/src/table/table.js b/plugins/woocommerce-admin/packages/components/src/table/table.js index d5d14c488c5..e79a14f0438 100644 --- a/plugins/woocommerce-admin/packages/components/src/table/table.js +++ b/plugins/woocommerce-admin/packages/components/src/table/table.js @@ -60,6 +60,7 @@ class Table extends Component { this.container = createRef(); this.sortBy = this.sortBy.bind( this ); this.updateTableShadow = this.updateTableShadow.bind( this ); + this.getRowKey = this.getRowKey.bind( this ); } componentDidMount() { @@ -123,6 +124,13 @@ class Table extends Component { } } + getRowKey( row, index ) { + if ( this.props.rowKey && typeof this.props.rowKey === 'function' ) { + return this.props.rowKey( row, index ); + } + return index; + } + render() { const { ariaHidden, @@ -245,7 +253,7 @@ class Table extends Component { { hasData ? ( rows.map( ( row, i ) => ( - + { row.map( ( cell, j ) => { const { cellClassName, @@ -306,12 +314,17 @@ class Table extends Component { headers[ j ].key, } ); + const cellKey = + this.getRowKey( + row, + i + ).toString() + j; return ( { getDisplay( cell ) } @@ -431,6 +444,11 @@ Table.propTypes = { * is checkboxes, for example). Set to false to disable row headers. */ rowHeader: PropTypes.oneOfType( [ PropTypes.number, PropTypes.bool ] ), + /** + * The rowKey used for the key value on each row, a function that returns the key. + * Defaults to index. + */ + rowKey: PropTypes.func, }; Table.defaultProps = { diff --git a/plugins/woocommerce-admin/packages/components/src/table/test/index.js b/plugins/woocommerce-admin/packages/components/src/table/test/index.js index afaf2cbabe2..917843eb156 100644 --- a/plugins/woocommerce-admin/packages/components/src/table/test/index.js +++ b/plugins/woocommerce-admin/packages/components/src/table/test/index.js @@ -74,4 +74,24 @@ describe( 'TableCard', () => { // We shouldn't get here if an error occurred. expect( true ).toBe( true ); } ); + + it( 'should render rows correctly with custom rowKey prop', () => { + render( + row[ 1 ].value } + /> + ); + + for ( const row of mockData ) { + expect( + screen.queryByText( row[ 0 ].display ) + ).toBeInTheDocument(); + } + } ); } );
{ isSortable ? ( @@ -286,7 +294,7 @@ class Table extends Component {