Add rowKey prop to table for allowing custom keys in rows (https://github.com/woocommerce/woocommerce-admin/pull/7196)
* Add rowKey prop to table for allowing custom keys in rows * Add changelog * Add test * Fix lint errors
This commit is contained in:
parent
d9daed0a4f
commit
2443b857f6
|
@ -1,6 +1,7 @@
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
- Revert Card component removal #7167.
|
- Revert Card component removal #7167.
|
||||||
|
- Add rowKey prop to Table and TableCard component. #7196
|
||||||
|
|
||||||
# 7.0.0
|
# 7.0.0
|
||||||
|
|
||||||
|
|
|
@ -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
|
`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)
|
`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
|
`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
|
### `labels` structure
|
||||||
|
|
||||||
|
@ -213,6 +214,7 @@ const rows = [
|
||||||
caption="Revenue Last Week"
|
caption="Revenue Last Week"
|
||||||
rows={ rows }
|
rows={ rows }
|
||||||
headers={ headers }
|
headers={ headers }
|
||||||
|
rowKey={ row => row.display }
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -228,6 +230,7 @@ Name | Type | Default | Description
|
||||||
`query` | Object | `{}` | The query string represented in object form
|
`query` | Object | `{}` | The query string represented in object form
|
||||||
`rows` | Array | `null` | (required) An array of arrays of display/value object pairs
|
`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
|
`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
|
### `headers` structure
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,7 @@ class TableCard extends Component {
|
||||||
summary,
|
summary,
|
||||||
title,
|
title,
|
||||||
totalRows,
|
totalRows,
|
||||||
|
rowKey,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { showCols } = this.state;
|
const { showCols } = this.state;
|
||||||
const allHeaders = this.props.headers;
|
const allHeaders = this.props.headers;
|
||||||
|
@ -238,6 +239,7 @@ class TableCard extends Component {
|
||||||
caption={ title }
|
caption={ title }
|
||||||
query={ query }
|
query={ query }
|
||||||
onSort={ onSort || onQueryChange( 'sort' ) }
|
onSort={ onSort || onQueryChange( 'sort' ) }
|
||||||
|
rowKey={ rowKey }
|
||||||
/>
|
/>
|
||||||
) }
|
) }
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
@ -350,6 +352,11 @@ TableCard.propTypes = {
|
||||||
* The total number of rows (across all pages).
|
* The total number of rows (across all pages).
|
||||||
*/
|
*/
|
||||||
totalRows: PropTypes.number.isRequired,
|
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 = {
|
TableCard.defaultProps = {
|
||||||
|
|
|
@ -11,7 +11,12 @@ import { rows, headers } from './index';
|
||||||
|
|
||||||
export const Basic = () => (
|
export const Basic = () => (
|
||||||
<Card size={ null }>
|
<Card size={ null }>
|
||||||
<Table caption="Revenue Last Week" rows={ rows } headers={ headers } />
|
<Table
|
||||||
|
caption="Revenue Last Week"
|
||||||
|
rows={ rows }
|
||||||
|
headers={ headers }
|
||||||
|
rowKey={ ( row ) => row[ 0 ].value }
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ class Table extends Component {
|
||||||
this.container = createRef();
|
this.container = createRef();
|
||||||
this.sortBy = this.sortBy.bind( this );
|
this.sortBy = this.sortBy.bind( this );
|
||||||
this.updateTableShadow = this.updateTableShadow.bind( this );
|
this.updateTableShadow = this.updateTableShadow.bind( this );
|
||||||
|
this.getRowKey = this.getRowKey.bind( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
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() {
|
render() {
|
||||||
const {
|
const {
|
||||||
ariaHidden,
|
ariaHidden,
|
||||||
|
@ -245,7 +253,7 @@ class Table extends Component {
|
||||||
<th
|
<th
|
||||||
role="columnheader"
|
role="columnheader"
|
||||||
scope="col"
|
scope="col"
|
||||||
key={ i }
|
key={ header.key || i }
|
||||||
{ ...thProps }
|
{ ...thProps }
|
||||||
>
|
>
|
||||||
{ isSortable ? (
|
{ isSortable ? (
|
||||||
|
@ -286,7 +294,7 @@ class Table extends Component {
|
||||||
</tr>
|
</tr>
|
||||||
{ hasData ? (
|
{ hasData ? (
|
||||||
rows.map( ( row, i ) => (
|
rows.map( ( row, i ) => (
|
||||||
<tr key={ i }>
|
<tr key={ this.getRowKey( row, i ) }>
|
||||||
{ row.map( ( cell, j ) => {
|
{ row.map( ( cell, j ) => {
|
||||||
const {
|
const {
|
||||||
cellClassName,
|
cellClassName,
|
||||||
|
@ -306,12 +314,17 @@ class Table extends Component {
|
||||||
headers[ j ].key,
|
headers[ j ].key,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const cellKey =
|
||||||
|
this.getRowKey(
|
||||||
|
row,
|
||||||
|
i
|
||||||
|
).toString() + j;
|
||||||
return (
|
return (
|
||||||
<Cell
|
<Cell
|
||||||
scope={
|
scope={
|
||||||
isHeader ? 'row' : null
|
isHeader ? 'row' : null
|
||||||
}
|
}
|
||||||
key={ j }
|
key={ cellKey }
|
||||||
className={ cellClasses }
|
className={ cellClasses }
|
||||||
>
|
>
|
||||||
{ getDisplay( cell ) }
|
{ getDisplay( cell ) }
|
||||||
|
@ -431,6 +444,11 @@ Table.propTypes = {
|
||||||
* is checkboxes, for example). Set to false to disable row headers.
|
* is checkboxes, for example). Set to false to disable row headers.
|
||||||
*/
|
*/
|
||||||
rowHeader: PropTypes.oneOfType( [ PropTypes.number, PropTypes.bool ] ),
|
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 = {
|
Table.defaultProps = {
|
||||||
|
|
|
@ -74,4 +74,24 @@ describe( 'TableCard', () => {
|
||||||
// We shouldn't get here if an error occurred.
|
// We shouldn't get here if an error occurred.
|
||||||
expect( true ).toBe( true );
|
expect( true ).toBe( true );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
it( 'should render rows correctly with custom rowKey prop', () => {
|
||||||
|
render(
|
||||||
|
<TableCard
|
||||||
|
title="Revenue"
|
||||||
|
headers={ mockHeaders }
|
||||||
|
isLoading={ false }
|
||||||
|
rows={ mockData }
|
||||||
|
rowsPerPage={ 1 }
|
||||||
|
totalRows={ 5 }
|
||||||
|
rowKey={ ( row ) => row[ 1 ].value }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
for ( const row of mockData ) {
|
||||||
|
expect(
|
||||||
|
screen.queryByText( row[ 0 ].display )
|
||||||
|
).toBeInTheDocument();
|
||||||
|
}
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
Loading…
Reference in New Issue