mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-12 21:10:24 +00:00
Enhanced expander and pivot (#215)
* Convert expander column to be more like a regular column. * Update story. * Simplify setting render on defaultExpander. * Add more control over expander and pivot columns using the column. * Fix default filtering on pivot column. * Add comments.
This commit is contained in:
committed by
Tanner Linsley
parent
42b5f5bb18
commit
bc7005db99
@@ -26,6 +26,7 @@ import NoDataText from '../stories/NoDataText.js'
|
||||
import Footers from '../stories/Footers.js'
|
||||
import Filtering from '../stories/Filtering.js'
|
||||
import ControlledTable from '../stories/ControlledTable.js'
|
||||
import PivotingOptions from '../stories/PivotingOptions.js'
|
||||
//
|
||||
configure(() => {
|
||||
storiesOf('1. Docs')
|
||||
@@ -51,6 +52,7 @@ configure(() => {
|
||||
.add('Pivoting & Aggregation', Pivoting)
|
||||
.add('Pivoting & Aggregation w/ Sub Components', PivotingSubComponents)
|
||||
.add('100k Rows w/ Pivoting & Sub Components', OneHundredKRows)
|
||||
.add('Pivoting Options', PivotingOptions)
|
||||
.add('Functional Rendering', FunctionalRendering)
|
||||
.add('Custom Expander Position', CustomExpanderPosition)
|
||||
.add('Custom "No Data" Text', NoDataText)
|
||||
|
||||
@@ -153,7 +153,6 @@ These are all of the available props (and their default values) for the main `<R
|
||||
pageSizeOptions: [5, 10, 20, 25, 50, 100],
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
expanderColumnWidth: 35,
|
||||
collapseOnSortingChange: true,
|
||||
collapseOnPageChange: true,
|
||||
collapseOnDataChange: true,
|
||||
@@ -258,6 +257,19 @@ These are all of the available props (and their default values) for the main `<R
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
// Global Expander Column Defaults
|
||||
expanderDefaults: {
|
||||
sortable: false,
|
||||
width: 35,
|
||||
hideFilter: true
|
||||
// render: will be overriden in methods.js to display ExpanderComponent
|
||||
},
|
||||
|
||||
// Global Pivot Column Defaults
|
||||
pivotDefaults: {
|
||||
// render: will be overriden in methods.js to display ExpanderComponent
|
||||
},
|
||||
|
||||
// Text
|
||||
previousText: 'Previous',
|
||||
@@ -307,8 +319,13 @@ Or just define them as props
|
||||
maxWidth: undefined, // A maximum width for this column.
|
||||
|
||||
// Special
|
||||
expander: false, // This option will override all data-related options and designates the column to be used
|
||||
// for pivoting and sub-component expansion
|
||||
// Turns this column into a special column for specifying expander and pivot column options.
|
||||
// If this option is true and there is NOT a pivot column, the `expanderDefaults` options will be applied on top of the column options.
|
||||
// If this option is true and there IS a pivot column, the `pivotDefaults` options will be applied on top of the column options.
|
||||
// Adding a column with the `expander` option set will allow you to rearrange expander and pivot column orderings in the table.
|
||||
// It will also let you specify rendering of the header (and header group if this special column is placed in the `columns` option of another column) and
|
||||
// the rendering of the expander itself.
|
||||
expander: false,
|
||||
|
||||
// Cell Options
|
||||
className: '', // Set the classname of the `td` element of the column
|
||||
|
||||
+17
-6
@@ -15,7 +15,6 @@ export default {
|
||||
pageSizeOptions: [5, 10, 20, 25, 50, 100],
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
expanderColumnWidth: 35,
|
||||
collapseOnSortingChange: true,
|
||||
collapseOnPageChange: true,
|
||||
collapseOnDataChange: true,
|
||||
@@ -120,6 +119,19 @@ export default {
|
||||
)
|
||||
},
|
||||
|
||||
// Global Expander Column Defaults
|
||||
expanderDefaults: {
|
||||
sortable: false,
|
||||
width: 35,
|
||||
hideFilter: true
|
||||
// render: will be overriden in methods.js to display ExpanderComponent
|
||||
},
|
||||
|
||||
// Global Pivot Column Defaults
|
||||
pivotDefaults: {
|
||||
// render: will be overriden in methods.js to display ExpanderComponent
|
||||
},
|
||||
|
||||
// Text
|
||||
previousText: 'Previous',
|
||||
nextText: 'Next',
|
||||
@@ -150,12 +162,11 @@ export default {
|
||||
},
|
||||
TdComponent: _.makeTemplateComponent('rt-td'),
|
||||
TfootComponent: _.makeTemplateComponent('rt-tfoot'),
|
||||
ExpanderComponent: ({isExpanded, ...rest}) => {
|
||||
ExpanderComponent: ({isExpanded}) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames('rt-expander', isExpanded && '-open')}
|
||||
{...rest}
|
||||
>•</div>
|
||||
<div className={classnames('rt-expander', isExpanded && '-open')}>
|
||||
•
|
||||
</div>
|
||||
)
|
||||
},
|
||||
PaginationComponent: Pagination,
|
||||
|
||||
+32
-113
@@ -10,6 +10,7 @@ export const ReactTableDefaults = defaultProps
|
||||
|
||||
export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
static defaultProps = defaultProps
|
||||
|
||||
constructor (props) {
|
||||
super()
|
||||
|
||||
@@ -41,6 +42,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
skipNextSort: false
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const resolvedState = this.getResolvedState()
|
||||
const {
|
||||
@@ -70,7 +72,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
getNoDataProps,
|
||||
getResizerProps,
|
||||
showPagination,
|
||||
expanderColumnWidth,
|
||||
manual,
|
||||
loadingText,
|
||||
noDataText,
|
||||
@@ -98,7 +99,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
ThComponent,
|
||||
TdComponent,
|
||||
TfootComponent,
|
||||
ExpanderComponent,
|
||||
PaginationComponent,
|
||||
LoadingComponent,
|
||||
SubComponent,
|
||||
@@ -229,39 +229,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
maxWidth: `${maxWidth}px`
|
||||
}
|
||||
|
||||
if (column.expander) {
|
||||
if (column.pivotColumns) {
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-pivot-header',
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
...flexStyles
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-expander-header',
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
@@ -372,7 +339,10 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
column: column
|
||||
})}
|
||||
{i < column.pivotColumns.length - 1 && (
|
||||
<ExpanderComponent />
|
||||
_.normalizeComponent(column.render, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
@@ -382,21 +352,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-expander-header',
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -500,7 +455,15 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
</span>
|
||||
)
|
||||
if (i < column.pivotColumns.length - 1) {
|
||||
pivotCols.push(<ExpanderComponent key={col.id + '-' + i} />)
|
||||
pivotCols.push(
|
||||
_.normalizeComponent(column.filterRender,
|
||||
{
|
||||
column,
|
||||
filter,
|
||||
key: col.id + '-' + i
|
||||
},
|
||||
defaultProps.column.filterRender
|
||||
))
|
||||
}
|
||||
}
|
||||
return (
|
||||
@@ -524,21 +487,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-expander-header',
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const filter = filtering.find(filter => filter.id === column.id)
|
||||
@@ -618,6 +566,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
...columnProps.style
|
||||
}
|
||||
|
||||
const extraProps = {}
|
||||
|
||||
if (column.expander) {
|
||||
const onTdClick = (e) => {
|
||||
if (onExpandRow) {
|
||||
@@ -634,6 +584,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
})
|
||||
}
|
||||
|
||||
extraProps['onClick'] = onTdClick
|
||||
|
||||
if (column.pivotColumns) {
|
||||
// Return the pivot expander cell
|
||||
const PivotCell = column.pivotRender
|
||||
@@ -656,9 +608,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
>
|
||||
{rowInfo.subRows ? (
|
||||
<span>
|
||||
<ExpanderComponent
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
{_.normalizeComponent(column.render, {
|
||||
...rowInfo,
|
||||
value: rowInfo.rowValues[column.id],
|
||||
isExpanded
|
||||
}, rowInfo.rowValues[column.id])}
|
||||
{column && column.pivotRender ? (
|
||||
<PivotCell
|
||||
{...rowInfo}
|
||||
@@ -668,37 +622,16 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
</span>
|
||||
) : SubComponent ? (
|
||||
<span>
|
||||
<ExpanderComponent
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
{_.normalizeComponent(column.render, {
|
||||
...rowInfo,
|
||||
value: rowInfo.rowValues[column.id],
|
||||
isExpanded
|
||||
}, rowInfo.rowValues[column.id])}
|
||||
</span>
|
||||
) : null}
|
||||
</TdComponent>
|
||||
)
|
||||
}
|
||||
|
||||
// Return the regular expander cell
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(
|
||||
classes,
|
||||
{hidden: !show}
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
onClick={onTdClick}
|
||||
>
|
||||
<span>
|
||||
<ExpanderComponent
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
</span>
|
||||
</TdComponent>
|
||||
)
|
||||
}
|
||||
|
||||
// Return regular cell
|
||||
@@ -716,10 +649,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
maxWidth: `${maxWidth}px`
|
||||
}}
|
||||
{...tdProps.rest}
|
||||
{...extraProps}
|
||||
>
|
||||
{_.normalizeComponent(column.render, {
|
||||
...rowInfo,
|
||||
value: rowInfo.rowValues[column.id]
|
||||
value: rowInfo.rowValues[column.id],
|
||||
isExpanded
|
||||
}, rowInfo.rowValues[column.id])}
|
||||
</TdComponent>
|
||||
)
|
||||
@@ -859,22 +794,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
</TdComponent>
|
||||
)
|
||||
}
|
||||
|
||||
// Return the regular expander cell
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(
|
||||
classes,
|
||||
{hidden: !show}
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
// Return regular cell
|
||||
|
||||
+51
-27
@@ -10,6 +10,7 @@ export default Base => class extends Base {
|
||||
}
|
||||
return resolvedState
|
||||
}
|
||||
|
||||
getDataModel (newState) {
|
||||
const {
|
||||
columns,
|
||||
@@ -18,7 +19,6 @@ export default Base => class extends Base {
|
||||
pivotIDKey,
|
||||
pivotValKey,
|
||||
subRowsKey,
|
||||
expanderColumnWidth,
|
||||
SubComponent
|
||||
} = newState
|
||||
|
||||
@@ -44,29 +44,42 @@ export default Base => class extends Base {
|
||||
currentSpan = []
|
||||
}
|
||||
|
||||
const noSubExpanderColumns = columns.map(col => {
|
||||
return {
|
||||
...col,
|
||||
columns: col.columns ? col.columns.filter(d => !d.expander) : undefined
|
||||
}
|
||||
})
|
||||
let columnsWithExpander = [...columns]
|
||||
|
||||
let expanderColumnIndex = columns.findIndex(col => col.expander)
|
||||
const needsExpander = (SubComponent || pivotBy.length) && expanderColumnIndex === -1
|
||||
const columnsWithExpander = needsExpander ? [{expander: true}, ...noSubExpanderColumns] : noSubExpanderColumns
|
||||
if (needsExpander) {
|
||||
expanderColumnIndex = 0
|
||||
let expanderColumn = columns.find(col => col.expander || (col.columns && col.columns.some(col2 => col2.expander)))
|
||||
// The actual expander might be in the columns field of a group column
|
||||
if (expanderColumn && !expanderColumn.expander) {
|
||||
expanderColumn = expanderColumn.columns.find(col => col.expander)
|
||||
}
|
||||
|
||||
// If it has subrows or pivot columns we need to make sure we have an expander column
|
||||
if ((SubComponent || pivotBy.length) && !expanderColumn) {
|
||||
expanderColumn = {expander: true}
|
||||
columnsWithExpander = [expanderColumn, ...columnsWithExpander]
|
||||
}
|
||||
|
||||
const makeDecoratedColumn = (column) => {
|
||||
const dcol = {
|
||||
...this.props.column,
|
||||
...column
|
||||
}
|
||||
|
||||
if (dcol.expander) {
|
||||
dcol.width = expanderColumnWidth
|
||||
return dcol
|
||||
let dcol
|
||||
if (pivotBy.length && column.expander) {
|
||||
dcol = {
|
||||
...this.props.column,
|
||||
render: this.props.ExpanderComponent,
|
||||
filterRender: this.props.ExpanderComponent,
|
||||
...this.props.pivotDefaults,
|
||||
...column
|
||||
}
|
||||
} else if (column.expander) {
|
||||
dcol = {
|
||||
...this.props.column,
|
||||
render: this.props.ExpanderComponent,
|
||||
...this.props.expanderDefaults,
|
||||
...column
|
||||
}
|
||||
} else {
|
||||
dcol = {
|
||||
...this.props.column,
|
||||
...column
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof dcol.accessor === 'string') {
|
||||
@@ -138,12 +151,24 @@ export default Base => class extends Base {
|
||||
pivotColumns.push(allDecoratedColumns[i])
|
||||
}
|
||||
}
|
||||
const pivotColumn = {
|
||||
...pivotColumns[0],
|
||||
pivotColumns,
|
||||
expander: true
|
||||
|
||||
const pivotExpanderColumn = visibleColumns.findIndex(col => col.expander || (col.columns && col.columns.some(col2 => col2.expander)))
|
||||
if (pivotExpanderColumn >= 0) {
|
||||
const pivotColumn = {
|
||||
...visibleColumns[pivotExpanderColumn],
|
||||
pivotColumns
|
||||
}
|
||||
visibleColumns[pivotExpanderColumn] = pivotColumn
|
||||
} else {
|
||||
// If the expander column wasn't on the top level column, find it in the `columns` option.
|
||||
const pivotExpanderSubColumn = visibleColumns[pivotExpanderColumn].columns.findIndex(col => col.expander)
|
||||
const pivotColumn = {
|
||||
...visibleColumns[pivotExpanderColumn].columns[pivotExpanderSubColumn],
|
||||
pivotColumns
|
||||
}
|
||||
// Add the pivot columns to the expander column
|
||||
visibleColumns[pivotExpanderColumn].columns[pivotExpanderSubColumn] = pivotColumn
|
||||
}
|
||||
visibleColumns[expanderColumnIndex] = pivotColumn
|
||||
}
|
||||
|
||||
// Build flast list of allVisibleColumns and HeaderGroups
|
||||
@@ -185,8 +210,7 @@ export default Base => class extends Base {
|
||||
})
|
||||
return aggregationValues
|
||||
}
|
||||
let standardColumns = pivotBy.length ? allVisibleColumns.slice(1) : allVisibleColumns
|
||||
const aggregatingColumns = standardColumns.filter(d => d.aggregate)
|
||||
const aggregatingColumns = allVisibleColumns.filter(d => !d.expander && d.aggregate)
|
||||
let pivotColumn
|
||||
if (pivotBy.length) {
|
||||
pivotColumn = allVisibleColumns[0]
|
||||
|
||||
@@ -8,8 +8,8 @@ import ReactTable from '../src/index'
|
||||
export default () => {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numLen: 0 }),
|
||||
lastName: namor.generate({ words: 1, numLen: 0 }),
|
||||
firstName: namor.generate({words: 1, numLen: 0}),
|
||||
lastName: namor.generate({words: 1, numLen: 0}),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
@@ -19,26 +19,33 @@ export default () => {
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? '...' : row.value}</span>
|
||||
}
|
||||
footer: () => <div style={{textAlign: 'center'}}>First Name</div>
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
accessor: 'lastName',
|
||||
footer: () => <div style={{textAlign: 'center'}}>Last Name</div>
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
|
||||
}
|
||||
footer: () => <div style={{textAlign: 'center'}}>Age</div>
|
||||
}]
|
||||
}, {
|
||||
expander: true
|
||||
header: 'Expand',
|
||||
columns: [{
|
||||
expander: true,
|
||||
header: () => (<strong>More</strong>),
|
||||
width: 65,
|
||||
render: ({isExpanded, ...rest}) => (
|
||||
<div>
|
||||
{isExpanded ? <span>⊙</span> : <span>⊕</span>}
|
||||
</div>
|
||||
),
|
||||
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'},
|
||||
footer: () => <span>♥</span>
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
@@ -71,26 +78,33 @@ const columns = [{
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? '...' : row.value}</span>
|
||||
}
|
||||
footer: () => <div style={{textAlign: 'center'}}>First Name</div>
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
accessor: 'lastName',
|
||||
footer: () => <div style={{textAlign: 'center'}}>Last Name</div>
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? \`$\{row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
footer: () => <div style={{textAlign: 'center'}}>Age</div>
|
||||
}]
|
||||
}, {
|
||||
expander: true
|
||||
header: 'Expand',
|
||||
columns: [{
|
||||
expander: true,
|
||||
header: () => (<strong>More</strong>),
|
||||
width: 65,
|
||||
render: ({isExpanded, ...rest}) => (
|
||||
<div>
|
||||
{isExpanded ? <span>⊙</span> : <span>⊕</span>}
|
||||
</div>
|
||||
),
|
||||
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'},
|
||||
footer: () => <span>♥</span>
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../src/index'
|
||||
|
||||
export default () => {
|
||||
const data = _.map(_.range(1000), d => {
|
||||
return {
|
||||
firstName: namor.generate({words: 1, numLen: 0}),
|
||||
lastName: namor.generate({words: 1, numLen: 0}),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => {
|
||||
return _.round(_.mean(vals))
|
||||
},
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
|
||||
}
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals),
|
||||
hideFilter: true
|
||||
}]
|
||||
}, {
|
||||
header: () => <strong>First ⇢ Last Name Pivot</strong>,
|
||||
expander: true,
|
||||
minWidth: 200,
|
||||
render: ({isExpanded, ...rest}) => (
|
||||
isExpanded ? <span> ➘ </span> : <span> ➙ </span>
|
||||
),
|
||||
filterRender: ({key}) => <span key={key}> ⥱ </span>,
|
||||
footer: () => <div style={{textAlign: 'center'}}><strong>Pivot Footer</strong></div>
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
showFilters={true}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>You can put any component you want here, even another React Table!</em>
|
||||
<br />
|
||||
<br />
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns.filter(x=>!x.expander)}
|
||||
defaultPageSize={3}
|
||||
showPagination={false}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>It even has access to the row data: </em>
|
||||
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => {
|
||||
return _.round(_.mean(vals))
|
||||
},
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals),
|
||||
hideFilter: true
|
||||
}]
|
||||
}, {
|
||||
header: () => <strong>First ⇢ Last Name Pivot</strong>,
|
||||
expander: true,
|
||||
minWidth: 200,
|
||||
render: ({isExpanded, ...rest}) => (
|
||||
isExpanded ? <span> ➘ </span> : <span> ➙ </span>
|
||||
),
|
||||
filterRender: ({key}) => <span key={key}> ⥱ </span>,
|
||||
footer: () => <div style={{textAlign: 'center'}}><strong>Pivot Footer</strong></div>
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
showFilters={true}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>You can put any component you want here, even another React Table!</em>
|
||||
<br />
|
||||
<br />
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns.filter(x=>!x.expander)}
|
||||
defaultPageSize={3}
|
||||
showPagination={false}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>It even has access to the row data: </em>
|
||||
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
`
|
||||
}
|
||||
Reference in New Issue
Block a user