From 75c31b9354ff8535371ec0fb5c1cc9d805896bc0 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Thu, 12 Jan 2017 11:06:09 -0700 Subject: [PATCH] Fully controlled component props and callbacks + docs --- README.md | 35 ++++++++++++++- src/index.js | 97 ++++++++++++++++++++++------------------ src/pagination.js | 13 +++--- stories/SubComponents.js | 36 +++++++++++---- 4 files changed, 121 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 2504c74..fe639ca 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ - [Header Groups](#header-groups) - [Sub Tables & Components](#sub-tables-components) - [Server-side Data](#server-side-data) +- [Fully Controlled Component](#fully-controlled-component) - [Multi-sort](#multi-sort) - [Component Overrides](#component-overrides) @@ -123,11 +124,15 @@ These are all of the available props (and their default values) for the main ` {...}} // Called when the page index is changed by the user + onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data + onSortingChange={(column, shiftKey) => {...}} // Called when a sortable column header is clicked with the column itself and if the shiftkey was held. + onExpand={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `visibleSubComponents` +/> +``` + ## 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! diff --git a/src/index.js b/src/index.js index 4a3ac23..9cb28eb 100644 --- a/src/index.js +++ b/src/index.js @@ -17,13 +17,18 @@ export const ReactTableDefaults = { showPageJump: true, expanderColumnWidth: 30, - // State Overrides (for controlled-component style) + // Controlled State Overrides // page // pageSize // sorting // visibleSubComponents - // Callbacks + // Controlled State Callbacks + onExpand: undefined, + onPageChange: undefined, + onPageSizeChange: undefined, + + // General Callbacks onChange: () => null, onTrClick: () => null, // Classes @@ -86,17 +91,17 @@ export const ReactTableDefaults = { ) }, TdComponent: _.makeTemplateComponent('rt-td'), - ExpanderComponent: ({isOpen, toggle, ...rest}) => { + ExpanderComponent: ({isExpanded, toggle, ...rest}) => { return (
) }, PaginationComponent: Pagination, - PreviousComponent: null, - NextComponent: null, + PreviousComponent: undefined, + NextComponent: undefined, LoadingComponent: ({loading, loadingText}) => (
@@ -116,7 +121,7 @@ export default React.createClass({ page: 0, pageSize: this.props.defaultPageSize || 10, sorting: false, - visibleSubComponents: {} + visibleSubComponents: [] } }, @@ -125,6 +130,7 @@ export default React.createClass({ }, render () { + const resolvedProps = this.getResolvedState() const { className, style, @@ -146,18 +152,11 @@ export default React.createClass({ trStyleCallback, tdStyle, showPagination, - showPageSizeOptions, - pageSizeOptions, - showPageJump, - previousText, - nextText, - pageText, - ofText, - rowsText, paginationClassName, expanderColumnWidth, manual, loadingText, + onExpand, // State visibleSubComponents, loading, @@ -173,11 +172,9 @@ export default React.createClass({ TdComponent, ExpanderComponent, PaginationComponent, - PreviousComponent, - NextComponent, LoadingComponent, SubComponent - } = this.getResolvedState() + } = resolvedProps // Build Columns const decoratedColumns = [] @@ -373,6 +370,8 @@ export default React.createClass({ index: row.__index, viewIndex: i } + const visibleSubComponentIndex = visibleSubComponents.indexOf(i) + const isExpanded = visibleSubComponentIndex > -1 return ( { + onClick={(e) => { + if (onExpand) { + return onExpand(i, e) + } + if (isExpanded) { + return this.setState({ + visibleSubComponents: [ + ...visibleSubComponents.slice(0, visibleSubComponentIndex - 1), + ...visibleSubComponents.slice(visibleSubComponentIndex + 1) + ] + }) + } this.setState({ - visibleSubComponents: { - ...visibleSubComponents, - [i]: !visibleSubComponents[i] - } + visibleSubComponents: [ + ...visibleSubComponents, + i + ] }) }} > )} @@ -424,7 +434,7 @@ export default React.createClass({ ) })} - {SubComponent && visibleSubComponents[i] ? ( + {SubComponent && isExpanded ? ( SubComponent(rowInfo) ) : null} @@ -468,25 +478,12 @@ export default React.createClass({ {showPagination && ( )} @@ -577,18 +574,30 @@ export default React.createClass({ }, // User actions - setPage (page) { + onPageChange (page) { + const { onPageChange } = this.props + if (onPageChange) { + return onPageChange(page) + } this.setState({ - visibleSubComponents: {}, + visibleSubComponents: [], page }, () => { this.fireOnChange() }) }, - setPageSize (newPageSize) { + onPageSizeChange (newPageSize) { + const { onPageSizeChange } = this.props const { pageSize, page } = this.getResolvedState() + + // Normalize the page to display const currentRow = pageSize * page const newPage = Math.floor(currentRow / pageSize) + + if (onPageSizeChange) { + return onPageSizeChange(newPageSize, newPage) + } + this.setState({ pageSize: newPageSize, page: newPage diff --git a/src/pagination.js b/src/pagination.js index 7f6d14c..8257545 100644 --- a/src/pagination.js +++ b/src/pagination.js @@ -22,7 +22,7 @@ export default React.createClass({ changePage (page) { page = this.getSafePage(page) this.setState({page}) - this.props.onChange(page) + this.props.onPageChange(page) }, applyPage (e) { e && e.preventDefault() @@ -31,8 +31,10 @@ export default React.createClass({ }, render () { const { - page, + // Computed pagesLength, + // Props + page, showPageSizeOptions, pageSizeOptions, pageSize, @@ -40,12 +42,11 @@ export default React.createClass({ canPrevious, canNext, onPageSizeChange, - className + className, + PreviousComponent = defaultButton, + NextComponent = defaultButton } = this.props - const PreviousComponent = this.props.previousComponent || defaultButton - const NextComponent = this.props.nextComponent || defaultButton - return (
{ data={data} columns={columns} defaultPageSize={10} - subComponent={(row) => { + SubComponent={(row) => { return (
- You can put any component you want here, even another React Table!. It has access to the row data: - {() => JSON.stringify(row, null, 2)} + You can put any component you want here, even another React Table! +
+
{ + defaultPageSize={3} + showPagination={false} + SubComponent={(row) => { return (
- You can put any component you want here, even another React Table! It even has access to the row data: + It even has access to the row data: {() => JSON.stringify(row, null, 2)}
) @@ -96,9 +98,27 @@ export default ( data={data} columns={columns} defaultPageSize={10} - subComponent={(row) => { + SubComponent={(row) => { return ( -
{JSON.stringify(row, null, 2)}
+
+ You can put any component you want here, even another React Table! +
+
+ { + return ( +
+ It even has access to the row data: + {() => JSON.stringify(row, null, 2)} +
+ ) + }} + /> +
) }} />