mirror of
https://github.com/gosticks/react-table.git
synced 2026-07-04 19:30:02 +00:00
Added more customization for functional rendering
This commit is contained in:
82
README.md
82
README.md
@@ -603,51 +603,77 @@ Here are the props and their corresponding callbacks that control the state of t
|
||||
```
|
||||
|
||||
## Functional Rendering
|
||||
Possibly one of the coolest features of React-Table is its ability to expose internal state for custom render logic. The easiest way to do this is to optionally pass a function as a child of `<ReactTable />`.
|
||||
Possibly one of the coolest features of React-Table is its ability to expose internal components and state for custom render logic. The easiest way to do this is to pass a function as the child of `<ReactTable />`.
|
||||
|
||||
The function you pass will be called with the following items:
|
||||
- Fully-resolved state of the table
|
||||
- The standard table generator
|
||||
- The standard table component (including individual partials as properties of this component)
|
||||
- The instance of the component
|
||||
|
||||
You can then return any JSX or react you want! This turns out to be perfect for:
|
||||
- Accessing the internal state of the table before rendering the table
|
||||
- Decorating the table with more UI
|
||||
- Building your own 100% custom display logic, while utilizing the state and methods of the table component
|
||||
- Reordering the internal components of the table
|
||||
- Accessing the internal state of the table without a `ref`
|
||||
- Decorating the table or extending it with your own UI
|
||||
- Building your own custom display logic
|
||||
|
||||
Example:
|
||||
Custom pagination order:
|
||||
```javascript
|
||||
<ReactTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
...
|
||||
columns={columns}
|
||||
>
|
||||
{(state, makeTable, instance) => {
|
||||
// Now you have full access to the state of the table!
|
||||
state.decoratedColumns === [...] // all of the columns (with id's and meta)
|
||||
state.visibleColumns === [...] // all of the columns (with id's and meta)
|
||||
state.visibleColumns === [...] // all of the columns (with id's and meta)
|
||||
// etc.
|
||||
|
||||
// `makeTable` is a function that returns the standard table markup
|
||||
return makeTable()
|
||||
|
||||
// So add some decoration!
|
||||
{(state, {
|
||||
Root,
|
||||
Table,
|
||||
HeaderGroups,
|
||||
Headers,
|
||||
Rows,
|
||||
Footers,
|
||||
Pagination,
|
||||
NoData,
|
||||
Loading
|
||||
}, instance) => {
|
||||
return (
|
||||
<div>
|
||||
<customPivotBySelect />
|
||||
<customColumnHideShow />
|
||||
<customAnything />
|
||||
{makeTable()}
|
||||
</div>
|
||||
<Root>
|
||||
<Pagination />
|
||||
<Table>
|
||||
<HeaderGroups />
|
||||
<Headers />
|
||||
<Rows />
|
||||
<Footers />
|
||||
</Table>
|
||||
<NoData />
|
||||
<Loading />
|
||||
</Root>
|
||||
)
|
||||
|
||||
// The possibilities are endless!!!
|
||||
|
||||
}}
|
||||
</ReactTable>
|
||||
```
|
||||
|
||||
Accessing internal state and wrapping with more UI:
|
||||
```javascript
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
>
|
||||
{(state, Table, instance) => {
|
||||
return (
|
||||
<div style={{
|
||||
background: '#ffcf00',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
padding: '5px'
|
||||
}}>
|
||||
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
|
||||
<Table />
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
```
|
||||
|
||||
The possibilities are endless!
|
||||
|
||||
## Multi-Sort
|
||||
When clicking on a column header, hold shift to multi-sort! You can toggle `ascending` `descending` and `none` for multi-sort columns. Clicking on a header without holding shift will clear the multi-sort and replace it with the single sort of that column. It's quite handy!
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="error-display"></div>
|
||||
<script src="static/preview.b1c267b204237cc2ab21.bundle.js"></script>
|
||||
<script src="static/preview.fe48f7ea9cf295bed07c.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/preview.b1c267b204237cc2ab21.bundle.js","sources":["webpack:///static/preview.b1c267b204237cc2ab21.bundle.js"],"mappings":"AAAA;AAkuDA;AAo5DA;AA8xFA;AA2+EA;AA++NA;AA06GA;AAgsDA;AA8/DA;AA4xDA;AAigEA;AAmjDA;AA4sDA;AAk8CA;AAu/DA;AA8lDA;AA09CA;AAqoDA;AAywEA;AAokDA;AAsvCA;AA2mDA;AA4tDA;AAqjEA;AAs2DA;AAmyDA;AAsnDA;AAszFA;AA65FA;AA4/CA;AAkzCA;AA6lCA;AA2qDA;AAkqBA;AAyZA;AAmyEA","sourceRoot":""}
|
||||
37
docs/static/preview.fe48f7ea9cf295bed07c.bundle.js
vendored
Normal file
37
docs/static/preview.fe48f7ea9cf295bed07c.bundle.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
docs/static/preview.fe48f7ea9cf295bed07c.bundle.js.map
vendored
Normal file
1
docs/static/preview.fe48f7ea9cf295bed07c.bundle.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/preview.fe48f7ea9cf295bed07c.bundle.js","sources":["webpack:///static/preview.fe48f7ea9cf295bed07c.bundle.js"],"mappings":"AAAA;AAkuDA;AA48CA;AA0sGA;AAigFA;AAyiNA;AA0rFA;AAk4FA;AAsiEA;AAwuDA;AAu9DA;AA6gDA;AAixDA;AA69CA;AAk+DA;AAqoDA;AAs9CA;AAgoDA;AAwsEA;AAuoDA;AAmvCA;AAioDA;AAkpDA;AA6lEA;AAs4DA;AAuyDA;AAokDA;AA0mFA;AAyiGA;AA2gDA;AAm2CA;AAy/BA;AA4uDA;AAy4BA;AA0XA;AA6zEA","sourceRoot":""}
|
||||
147
src/index.js
147
src/index.js
@@ -702,13 +702,14 @@ export default React.createClass({
|
||||
)
|
||||
}
|
||||
|
||||
const makeTable = () => {
|
||||
const rootProps = _.splitProps(getProps(finalState, undefined, undefined, this))
|
||||
const tableProps = _.splitProps(getTableProps(finalState, undefined, undefined, this))
|
||||
const tBodyProps = _.splitProps(getTbodyProps(finalState, undefined, undefined, this))
|
||||
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this))
|
||||
const loadingProps = getLoadingProps(finalState, undefined, undefined, this)
|
||||
const noDataProps = getNoDataProps(finalState, undefined, undefined, this)
|
||||
const rootProps = _.splitProps(getProps(finalState, undefined, undefined, this))
|
||||
const tableProps = _.splitProps(getTableProps(finalState, undefined, undefined, this))
|
||||
const tBodyProps = _.splitProps(getTbodyProps(finalState, undefined, undefined, this))
|
||||
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this))
|
||||
const loadingProps = getLoadingProps(finalState, undefined, undefined, this)
|
||||
const noDataProps = getNoDataProps(finalState, undefined, undefined, this)
|
||||
|
||||
const Root = ({children}) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
@@ -722,56 +723,96 @@ export default React.createClass({
|
||||
}}
|
||||
{...rootProps.rest}
|
||||
>
|
||||
<TableComponent
|
||||
className={classnames(tableProps.className)}
|
||||
style={tableProps.style}
|
||||
{...tableProps.rest}
|
||||
>
|
||||
{hasHeaderGroups && makeHeaderGroups()}
|
||||
{makeHeaders()}
|
||||
<TbodyComponent
|
||||
className={classnames(tBodyProps.className)}
|
||||
style={{
|
||||
...tBodyProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
}}
|
||||
{...tBodyProps.rest}
|
||||
>
|
||||
{pageRows.map((d, i) => makePageRow(d, i))}
|
||||
{padRows.map(makePadRow)}
|
||||
</TbodyComponent>
|
||||
{hasColumnFooter && makeColumnFooters()}
|
||||
</TableComponent>
|
||||
{showPagination && (
|
||||
<PaginationComponent
|
||||
{...resolvedState}
|
||||
pages={pages}
|
||||
canPrevious={canPrevious}
|
||||
canNext={canNext}
|
||||
onPageChange={this.onPageChange}
|
||||
onPageSizeChange={this.onPageSizeChange}
|
||||
className={paginationProps.className}
|
||||
style={paginationProps.style}
|
||||
{...paginationProps.rest}
|
||||
/>
|
||||
)}
|
||||
{!pageRows.length && (
|
||||
<NoDataComponent
|
||||
{...noDataProps}
|
||||
>
|
||||
{_.normalizeComponent(noDataText)}
|
||||
</NoDataComponent>
|
||||
)}
|
||||
<LoadingComponent
|
||||
loading={loading}
|
||||
loadingText={loadingText}
|
||||
{...loadingProps}
|
||||
/>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Table = ({children}) => (
|
||||
<TableComponent
|
||||
className={classnames(tableProps.className)}
|
||||
style={tableProps.style}
|
||||
{...tableProps.rest}
|
||||
>
|
||||
{children}
|
||||
</TableComponent>
|
||||
)
|
||||
|
||||
const HeaderGroups = () => hasHeaderGroups ? makeHeaderGroups() : null
|
||||
const Headers = () => makeHeaders()
|
||||
const Rows = ({children}) => (
|
||||
<TbodyComponent
|
||||
className={classnames(tBodyProps.className)}
|
||||
style={{
|
||||
...tBodyProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
}}
|
||||
{...tBodyProps.rest}
|
||||
>
|
||||
{pageRows.map((d, i) => makePageRow(d, i))}
|
||||
{padRows.map(makePadRow)}
|
||||
</TbodyComponent>
|
||||
)
|
||||
|
||||
const Footers = () => hasColumnFooter ? makeColumnFooters() : null
|
||||
|
||||
const Pagination = () => showPagination ? (
|
||||
<PaginationComponent
|
||||
{...resolvedState}
|
||||
pages={pages}
|
||||
canPrevious={canPrevious}
|
||||
canNext={canNext}
|
||||
onPageChange={this.onPageChange}
|
||||
onPageSizeChange={this.onPageSizeChange}
|
||||
className={paginationProps.className}
|
||||
style={paginationProps.style}
|
||||
{...paginationProps.rest}
|
||||
/>
|
||||
) : null
|
||||
|
||||
const NoData = () => !pageRows.length ? (
|
||||
<NoDataComponent
|
||||
{...noDataProps}
|
||||
>
|
||||
{_.normalizeComponent(noDataText)}
|
||||
</NoDataComponent>
|
||||
) : null
|
||||
|
||||
const Loading = () => (
|
||||
<LoadingComponent
|
||||
loading={loading}
|
||||
loadingText={loadingText}
|
||||
{...loadingProps}
|
||||
/>
|
||||
)
|
||||
|
||||
const StandardTable = () => (
|
||||
<Root>
|
||||
<Table>
|
||||
<HeaderGroups />
|
||||
<Headers />
|
||||
<Rows />
|
||||
<Footers />
|
||||
</Table>
|
||||
<Pagination />
|
||||
<NoData />
|
||||
<Loading />
|
||||
</Root>
|
||||
)
|
||||
|
||||
Object.assign(StandardTable, {
|
||||
Root,
|
||||
Table,
|
||||
HeaderGroups,
|
||||
Headers,
|
||||
Rows,
|
||||
Footers,
|
||||
Pagination,
|
||||
NoData,
|
||||
Loading
|
||||
})
|
||||
|
||||
// childProps are optionally passed to a function-as-a-child
|
||||
return children ? children(finalState, makeTable, this) : makeTable()
|
||||
return children ? children(finalState, StandardTable, this) : <StandardTable />
|
||||
}
|
||||
})
|
||||
|
||||
@@ -30,7 +30,6 @@ $expandSize = 7px
|
||||
|
||||
.rt-th
|
||||
.rt-td
|
||||
color: black
|
||||
border-right: 1px solid alpha(black, .05)
|
||||
transition box-shadow .3s $easeOutBack
|
||||
box-shadow:inset 0 0 0 0 transparent
|
||||
@@ -103,7 +102,6 @@ $expandSize = 7px
|
||||
.rt-tfoot
|
||||
display: flex
|
||||
flex-direction: column
|
||||
background: white
|
||||
box-shadow: 0 0px 15px 0px alpha(black, .15)
|
||||
|
||||
.rt-td
|
||||
|
||||
@@ -40,22 +40,169 @@ export default () => {
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
accessor: 'firstName',
|
||||
footer: 'Footer'
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
accessor: d => d.lastName,
|
||||
footer: 'Footer'
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
accessor: 'age',
|
||||
footer: 'Footer'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<strong>Functional rendering</strong> simply means that you have all of the building blocks to render your own React Table however you'd like.
|
||||
<br />
|
||||
<br />
|
||||
Whether it's <strong>completely custom</strong>, or even just <strong>rearranging the order of the table's elements</strong>, this is how you can do it.
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<strong>Pagination at the top using partials:</strong>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
>
|
||||
{(state, {
|
||||
Root,
|
||||
Table,
|
||||
HeaderGroups,
|
||||
Headers,
|
||||
Rows,
|
||||
Footers,
|
||||
Pagination,
|
||||
NoData,
|
||||
Loading
|
||||
}, instance) => {
|
||||
return (
|
||||
<Root>
|
||||
<Pagination />
|
||||
<Table>
|
||||
<HeaderGroups />
|
||||
<Headers />
|
||||
<Rows />
|
||||
<Footers />
|
||||
</Table>
|
||||
<NoData />
|
||||
<Loading />
|
||||
</Root>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
</div>
|
||||
|
||||
<CodeHighlight>{() => `
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
>
|
||||
{(state, {
|
||||
Root,
|
||||
Table,
|
||||
HeaderGroups,
|
||||
Headers,
|
||||
Rows,
|
||||
Footers,
|
||||
Pagination,
|
||||
NoData,
|
||||
Loading
|
||||
}, instance) => {
|
||||
return (
|
||||
<Root>
|
||||
<Pagination />
|
||||
<Table>
|
||||
<HeaderGroups />
|
||||
<Headers />
|
||||
<Rows />
|
||||
<Footers />
|
||||
</Table>
|
||||
<NoData />
|
||||
<Loading />
|
||||
</Root>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
)
|
||||
`}</CodeHighlight>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<strong>Wrapping the standard table output</strong>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
>
|
||||
{(state, Table, instance) => {
|
||||
return (
|
||||
<div style={{
|
||||
background: '#ffcf00',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
padding: '5px'
|
||||
}}>
|
||||
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
|
||||
<Table />
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
</div>
|
||||
|
||||
<CodeHighlight>{() => `
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
>
|
||||
{(state, Table, instance) => {
|
||||
return (
|
||||
<div style={{
|
||||
background: '#ffcf00',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
padding: '5px'
|
||||
}}>
|
||||
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
|
||||
<Table />
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
)
|
||||
`}</CodeHighlight>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<strong>Need more control? This is the entire table state and component instance at your disposal!</strong>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
@@ -63,54 +210,23 @@ export default () => {
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
>
|
||||
{(state, makeTable, instance) => {
|
||||
console.log(state)
|
||||
{(state, StandardTable, instance) => {
|
||||
return (
|
||||
<div>
|
||||
Look! This is the entire table state and component instance at your disposal!
|
||||
<JSONTree
|
||||
data={Object.assign({}, state, {children: 'function () {...}'})}
|
||||
theme={JSONtheme}
|
||||
invertTheme
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
{makeTable()}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
</div>
|
||||
<br />
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
<CodeHighlight>{() => `
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
// Create some column definitions
|
||||
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'
|
||||
}]
|
||||
}]
|
||||
|
||||
// Display your table!
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
@@ -118,23 +234,20 @@ return (
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
>
|
||||
{(state, makeTable, instance) => {
|
||||
console.log(state)
|
||||
{(state, StandardTable, instance) => {
|
||||
return (
|
||||
<div>
|
||||
Look! This is the entire table state and component instance at your disposal!
|
||||
<JSONTree
|
||||
data={Object.assign({}, state, {children: 'function () {...}'})}
|
||||
theme={JSONtheme}
|
||||
invertTheme
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
{makeTable()}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
)
|
||||
`
|
||||
`}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user