Skip to content

Commit

Permalink
Add valueGetter to Table component (#434)
Browse files Browse the repository at this point in the history
* Add valueGetter to Table component

* Manually update documentation
  • Loading branch information
mwislek authored Jul 14, 2020
1 parent d14fc18 commit 7d2b33a
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 26 deletions.
2 changes: 2 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,7 @@ This component's behavior is largely determined by the [TableColumn][101] compon

- `data` **[Array][145]** An array of objects to display in the table- one object per row (optional, default `[]`)
- `initialColumn` **[Number][144]** The name of the column that's initially selected (optional, default `''`)
- `initialAscending` **[Boolean][142]** The sort direction of the initial column (optional, default `true`)
- `disableReverse` **[Boolean][142]** Disables automatic reversing of descending sorts (optional, default `false`)
- `disableSort` **[Boolean][142]** A flag to disable sorting on all columns and hide sorting arrows. (optional, default `false`)
- `controlled` **[Boolean][142]** A flag to disable sorting on all columns, while keeping the sorting arrows. Used when sorting is controlled by an external source. (optional, default `false`)
Expand Down Expand Up @@ -1352,6 +1353,7 @@ A component used to pass column information to a [Table][95] or [SortableTable][
- `format` **[Function][141]?** A function that formats the value displayed in each cell in the column
- `disabled` **[Boolean][142]?** A flag that disables sorting for the column
- `placeholder` **[String][140]?** A string that will be displayed if the value of the cell is `undefined` or `null`
- `valueGetter` **[Function][141]?** A function that will return a cell's value derived from each data object. Will be passed the `data` for the row.

### Examples

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@launchpadlab/lp-components",
"version": "3.31.4",
"version": "3.32.0",
"engines": {
"node": "^8.0.0 || ^10.13.0 || ^12.0.0"
},
Expand Down
18 changes: 10 additions & 8 deletions src/tables/components/table-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ function TableRow ({
<RowComponent { ...{ data: rowData } }>
{
columns.map((column, key) => {
const { name, component: CellComponent=DefaultCellComponent, format=identity, onClick=noop, ...rest } = column
const value = format(get(name, rowData))
const { name, component: CellComponent=DefaultCellComponent, format=identity, onClick=noop, valueGetter, ...rest } = column
const cellValue =
valueGetter ? valueGetter(rowData) : get(name, rowData)
const value = format(cellValue)
const onColClick = column.disabled ? noop : () => onClick(rowData)
return <CellComponent { ...{ // eslint-disable-line
key,
value,
name,
data: rowData,
onClick: onColClick,
...rest
key,
value,
name,
data: rowData,
onClick: onColClick,
...rest
} } />
})
}
Expand Down
1 change: 1 addition & 0 deletions src/tables/helpers/column-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const columnPropTypes = {
headerComponent: componentType,
onClick: PropTypes.func,
format: PropTypes.func,
valueGetter: PropTypes.func,
}

export const Types = {
Expand Down
23 changes: 12 additions & 11 deletions src/tables/sortable-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@ import React from 'react'
import PropTypes from 'prop-types'
import { sortable, sortablePropTypes, noop } from '../utils'
import { getColumnData, Types } from './helpers'
import { TableHeader as DefaultHeader, TableRow as Row } from './components'
import { TableHeader as DefaultHeader, TableRow as Row } from './components'
import classnames from 'classnames'

/**
* A component for displaying sortable data in a table.
* This component's behavior is largely determined by the {@link TableColumn} components that are passed to it.
*
*
* @name SortableTable
* @type Function
* @param {Array} [data=[]] - An array of objects to display in the table- one object per row
* @param {Number} [initialColumn=''] - The name of the column that's initially selected
* @param {Boolean} [initialAscending=true] - The sort direction of the initial column
* @param {Boolean} [disableReverse=false] - Disables automatic reversing of descending sorts
* @param {Boolean} [disableSort=false] - A flag to disable sorting on all columns and hide sorting arrows.
* @param {Boolean} [controlled=false] - A flag to disable sorting on all columns, while keeping the sorting arrows. Used when sorting is controlled by an external source.
* @param {Boolean} [controlled=false] - A flag to disable sorting on all columns, while keeping the sorting arrows. Used when sorting is controlled by an external source.
* @param {Function} [onChange] - A callback that will be fired when the sorting state changes
* @param {Function} [rowComponent] - A custom row component for the table. Will be passed the `data` for the row, as well as `children` to render.
* @param {Function} [headerComponent] - A custom header component for the table. Will be passed the configuration of the corresponding column, as well as the current `sortPath` / `ascending` and an `onClick` handler. May be overridden by a custom `headerComponent` for a column.
* @example
*
*
* function PersonTable ({ people }) {
* return (
* <SortableTable data={ people } initialColumn="name">
Expand Down Expand Up @@ -49,15 +50,15 @@ const defaultProps = {
className: ''
}

function SortableTable ({
function SortableTable ({
columns,
data: unsortedData,
data: unsortedData,
disableSort,
controlled,
sort,
ascending,
sortPath,
setSortPath,
sort,
ascending,
sortPath,
setSortPath,
setSortFunc,
rowComponent,
headerComponent,
Expand Down Expand Up @@ -91,7 +92,7 @@ function SortableTable ({
</tr></thead>
<tbody>
{
data.map((rowData, key) =>
data.map((rowData, key) =>
<Row {...{
key,
rowData,
Expand Down
5 changes: 3 additions & 2 deletions src/tables/table-column.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { columnPropTypes } from './helpers'

/**
* A component used to pass column information to a {@link Table} or {@link SortableTable}.
*
*
* @name TableColumn
* @type Function
* @param {String} name - The key of the value to display in the column from each data object
Expand All @@ -14,8 +14,9 @@ import { columnPropTypes } from './helpers'
* @param {Function} [format] - A function that formats the value displayed in each cell in the column
* @param {Boolean} [disabled] - A flag that disables sorting for the column
* @param {String} [placeholder] - A string that will be displayed if the value of the cell is `undefined` or `null`
* @param{Function} [valueGetter] - A function that will return a cell's value derived from each data object. Will be passed the `data` for the row.
* @example
*
*
* function PersonTable ({ people }) {
* return (
* <SortableTable data={ people } initialColumn="name">
Expand Down
14 changes: 13 additions & 1 deletion stories/tables/sortable-table.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ function CustomHeader ({ column: { name } }) {
)
}

function createCustomValue(data) {
return `${data.name}:${data.age}`
}

storiesOf('SortableTable', module)
.add('default', () => (
<SortableTable data={ tableData }>
Expand Down Expand Up @@ -103,4 +107,12 @@ storiesOf('SortableTable', module)
<Column name="age" format={ val => val.toFixed(1) } />
<Column name="active" format={ val => val === 'yes' ? 'Y' : 'N' } />
</SortableTable>
))
))
.add('with custom value getter', () => (
<SortableTable data={ tableData }>
<Column name="name" format={ lowerCase }/>
<Column name="age" format={ val => val.toFixed(1) } />
<Column name="active" format={ val => val === 'yes' ? 'Y' : 'N' } />
<Column name="nameAndAge" valueGetter={createCustomValue} />
</SortableTable>
))
22 changes: 19 additions & 3 deletions test/tables/sortable-table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ test('column can have custom className', () => {
})

test('column can have custom cell component', () => {
const MyCell = () => <td> Hi! </td>
const MyCell = () => <td> Hi! </td>
const wrapper = mount(
<SortableTable data={ tableData }>
<Column name="name" component={ MyCell }/>
Expand Down Expand Up @@ -232,7 +232,7 @@ test('`format` updates the cell value', () => {

test('`placeholder` option is displayed if value is `null` or `undefined`', () => {
const data = [
{ name: null },
{ name: null },
{ name: undefined },
]
const wrapper = mount(
Expand All @@ -246,7 +246,7 @@ test('`placeholder` option is displayed if value is `null` or `undefined`', () =

test('can recieve custom class name', () => {
const data = [
{ name: null },
{ name: null },
{ name: undefined },
]
const wrapper = mount(
Expand All @@ -256,3 +256,19 @@ test('can recieve custom class name', () => {
)
expect(wrapper.find('table.foo').exists()).toBe(true)
})

test('`valueGetter` derives the cell value', () => {
const data = [
{ name: 'Opportunity 1', accountName: 'Dealer 1' },
{ name: 'Opportunity 2', accountName: 'Dealer 2' },
]
const myValueGetter = jest.fn((data) => `${data.name} - ${data.accountName}`)
const wrapper = mount(
<SortableTable data={ data } >
<Column name="opportunityName" valueGetter={ myValueGetter } />
</SortableTable>
)
expect(wrapper.find('td').first().text()).toEqual('Opportunity 1 - Dealer 1')
expect(wrapper.find('td').last().text()).toEqual('Opportunity 2 - Dealer 2')
expect(myValueGetter).toHaveBeenCalled()
})

0 comments on commit 7d2b33a

Please sign in to comment.