diff --git a/README.md b/README.md index 07b5197..736f8bc 100644 --- a/README.md +++ b/README.md @@ -163,9 +163,9 @@ These are all of the available props (and their default values) for the main ` ({}), filterMethod: undefined, - sortMethod: undefined, - hideFilter: false + sortMethod: undefined }, // Global Expander Column Defaults expanderDefaults: { sortable: false, resizable: false, - width: 35, - hideFilter: true + filterable: false, + width: 35 }, // Global Pivot Column Defaults @@ -356,7 +356,9 @@ Or just define them as props // General accessor: 'propertyName', // or Accessor eg. (row) => row.propertyName (see "Accessors" section for more details) id: 'myProperty', // Conditional - A unique ID is required if the accessor is not a string or if you would like to override the column name used in server-side calls - sortable: true, + sortable: boolean, // Overrides the table option + resizable: boolean, // Overrides the table option + filterable: boolean, // Overrides the table option show: true, // can be used to hide a column width: undefined, // A hardcoded width for the column. This overrides both min and max width options minWidth: 100, // A minimum width for this column. If there is extra room, column will flex to fill available space (up to the max-width, if set) @@ -394,7 +396,6 @@ Or just define them as props // filter == an object specifying which filter is being applied. Format: {id: [the filter column's id], value: [the value the user typed in the filter field], pivotId: [if filtering on a pivot column, the pivotId will be set to the pivot column's id and the `id` field will be set to the top level pivoting column]} // row == the row of data supplied to the table // column == the column that the filter is on - hideFilter: false, // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row }] ``` @@ -836,9 +837,9 @@ defaultSortMethod = (a, b) => { ``` ## Filtering -Filtering can be enabled by setting the `showFilters` option on the table. +Filtering can be enabled by setting the `filterable` option on the table. -If you don't want particular column to be filtered you can set the `hideFilter` option on the column. +If you don't want particular column to be filtered you can set the `filterable={false}` option on the column. By default the table tries to filter by checking if the row's value starts with the filter text. The default method for filtering the table can be set with the table's `defaultFilterMethod` option. diff --git a/src/defaultProps.js b/src/defaultProps.js index fcfac93..bbaf93d 100644 --- a/src/defaultProps.js +++ b/src/defaultProps.js @@ -19,9 +19,9 @@ export default { collapseOnPageChange: true, collapseOnDataChange: true, freezeWhenExpanded: false, - showFilters: false, sortable: true, resizable: true, + filterable: false, defaultSorted: [], defaultFiltered: [], defaultResized: [], @@ -123,6 +123,7 @@ export default { // All Columns sortable: undefined, // use table default resizable: undefined, // use table default + filterable: undefined, // use table default show: true, minWidth: 100, // Cells only @@ -140,16 +141,15 @@ export default { footerStyle: {}, getFooterProps: emptyObj, filterMethod: undefined, - sortMethod: undefined, - hideFilter: false + sortMethod: undefined }, // Global Expander Column Defaults expanderDefaults: { sortable: false, resizable: false, - width: 35, - hideFilter: true + filterable: false, + width: 35 }, pivotDefaults: { diff --git a/src/index.js b/src/index.js index cff2d17..4aefcc3 100644 --- a/src/index.js +++ b/src/index.js @@ -75,9 +75,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { manual, loadingText, noDataText, - showFilters, sortable, resizable, + filterable, // Pivoting State pivotIDKey, pivotValKey, @@ -134,6 +134,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { const padRows = _.range(Math.max(minRows - pageRows.length, 0)) const hasColumnFooter = allVisibleColumns.some(d => d.Footer) + const hasFilters = filterable || allVisibleColumns.some(d => d.filterable) const recurseRowsViewIndex = (rows, path = [], index = -1) => { return [ @@ -400,6 +401,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { const ResolvedFilterComponent = column.Filter || FilterComponent + const isFilterable = _.getFirstDefined(column.filterable, filterable, false) + return ( - {!column.hideFilter ? ( + {isFilterable ? ( _.normalizeComponent(ResolvedFilterComponent, { column, @@ -788,7 +791,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) { > {hasHeaderGroups ? makeHeaderGroups() : null} {makeHeaders()} - {showFilters ? makeFilters() : null} + {hasFilters ? makeFilters() : null} class extends Base { const oldState = this.getResolvedState() const newState = this.getResolvedState(nextProps, nextState) - if (JSON.stringify(oldState.defaultSorted) !== JSON.stringify(newState.defaultSorted)) { - newState.sorted = newState.defaultSorted - } + // Do a deep compare of new and old `defaultOption` and + // if they are different reset `option = defaultOption` + const defaultableOptions = ['sorted', 'filtered', 'resized', 'expanded'] + defaultableOptions.forEach(x => { + const defaultName = `default${x.charAt(0).toUpperCase() + x.slice(1)}` + if (JSON.stringify(oldState[defaultName]) !== JSON.stringify(newState[defaultName])) { + newState[x] = newState[defaultName] + } + }) - if ((oldState.showFilters !== newState.showFilters) || - (oldState.showFilters !== newState.showFilters)) { - newState.filtered = newState.defaultFiltered - } + // If they change these table options, we need to reset defaults + // or else we could get into a state where the user has changed the UI + // and then disabled the ability to change it back. + // e.g. If `filterable` has changed, set `filtered = defaultFiltered` + const resettableOptions = ['sortable', 'filterable', 'resizable'] + resettableOptions.forEach(x => { + if (oldState[x] !== newState[x]) { + const baseName = x.replace('able', '') + const optionName = `${baseName}ed` + const defaultName = `default${optionName.charAt(0).toUpperCase() + optionName.slice(1)}` + newState[optionName] = newState[defaultName] + } + }) // Props that trigger a data update if ( @@ -27,7 +42,6 @@ export default Base => class extends Base { oldState.columns !== newState.columns || oldState.pivotBy !== newState.pivotBy || oldState.sorted !== newState.sorted || - oldState.showFilters !== newState.showFilters || oldState.filtered !== newState.filtered ) { this.setStateWithData(this.getDataModel(newState)) diff --git a/src/methods.js b/src/methods.js index ecaefeb..8b087ec 100644 --- a/src/methods.js +++ b/src/methods.js @@ -272,7 +272,6 @@ export default Base => class extends Base { manual, sorted, filtered, - showFilters, defaultFilterMethod, resolvedData, allVisibleColumns, @@ -282,17 +281,16 @@ export default Base => class extends Base { const sortMethodsByColumnID = {} allDecoratedColumns - .filter(col => col.sortMethod) - .forEach(col => { - sortMethodsByColumnID[col.id] = col.sortMethod - }) + .filter(col => col.sortMethod) + .forEach(col => { + sortMethodsByColumnID[col.id] = col.sortMethod + }) // Resolve the data from either manual data or sorted data return { sortedData: manual ? resolvedData : this.sortData( this.filterData( resolvedData, - showFilters, filtered, defaultFilterMethod, allVisibleColumns @@ -315,10 +313,10 @@ export default Base => class extends Base { return _.getFirstDefined(this.state[key], this.props[key]) } - filterData (data, showFilters, filtered, defaultFilterMethod, allVisibleColumns) { + filterData (data, filtered, defaultFilterMethod, allVisibleColumns) { let filteredData = data - if (showFilters && filtered.length) { + if (filtered.length) { filteredData = filtered.reduce( (filteredSoFar, nextFilter) => { return filteredSoFar.filter( @@ -332,9 +330,9 @@ export default Base => class extends Base { column = column.pivotColumns.find(x => x.id === nextFilter.id) } - // Don't filter hidden columns - if (!column) { - return + // Don't filter hidden columns or columns that have had their filters disabled + if (!column || column.filterable === false) { + return true } const filterMethod = column.filterMethod || defaultFilterMethod @@ -353,7 +351,7 @@ export default Base => class extends Base { } return { ...row, - [this.props.subRowsKey]: this.filterData(row[this.props.subRowsKey], showFilters, filtered, defaultFilterMethod, allVisibleColumns) + [this.props.subRowsKey]: this.filterData(row[this.props.subRowsKey], filtered, defaultFilterMethod, allVisibleColumns) } }).filter(row => { if (!row[this.props.subRowsKey]) { diff --git a/stories/ControlledTable.js b/stories/ControlledTable.js index 5882a16..57d2ed7 100644 --- a/stories/ControlledTable.js +++ b/stories/ControlledTable.js @@ -51,7 +51,7 @@ class Story extends React.Component { data={data} columns={columns} pivotBy={['lastName']} - showFilters + filterable // Controlled Props sorted={this.state.sorted} page={this.state.page} diff --git a/stories/Filtering.js b/stories/Filtering.js index 735082f..b85f526 100644 --- a/stories/Filtering.js +++ b/stories/Filtering.js @@ -28,7 +28,7 @@ class Story extends React.Component { collapseOnPageChange: true, collapseOnDataChange: true, freezeWhenExpanded: false, - showFilters: true, + filterable: true, sortable: true, resizable: true }, diff --git a/stories/PivotingOptions.js b/stories/PivotingOptions.js index 1a505f0..f1263d0 100644 --- a/stories/PivotingOptions.js +++ b/stories/PivotingOptions.js @@ -41,7 +41,7 @@ class Story extends React.Component { Header: 'Visits', accessor: 'visits', aggregate: vals => _.sum(vals), - hideFilter: true + filterable: false }] }, { pivot: true, @@ -81,7 +81,7 @@ class Story extends React.Component { pivotBy={['firstName', 'lastName']} defaultSorted={[{id: 'firstName', desc: false}, {id: 'lastName', desc: true}]} collapseOnSortingChange={false} - showFilters + filterable ExpanderComponent={({isExpanded, ...rest}) => ( isExpanded ? : )} diff --git a/stories/PivotingSubComponents.js b/stories/PivotingSubComponents.js index 5100dc8..56a6589 100644 --- a/stories/PivotingSubComponents.js +++ b/stories/PivotingSubComponents.js @@ -39,7 +39,7 @@ class Story extends React.Component { Header: 'Visits', accessor: 'visits', aggregate: vals => _.sum(vals), - hideFilter: true + filterable: false }] }] @@ -52,7 +52,7 @@ class Story extends React.Component { defaultPageSize={10} className='-striped -highlight' pivotBy={['firstName', 'lastName']} - showFilters + filterable SubComponent={(row) => { return (
diff --git a/stories/ServerSide.js b/stories/ServerSide.js index b0b6e61..35999e5 100644 --- a/stories/ServerSide.js +++ b/stories/ServerSide.js @@ -92,7 +92,7 @@ class Story extends React.Component { }]} manual // Forces table not to paginate or sort automatically, so we can handle it server-side defaultPageSize={10} - showFilters + filterable data={this.state.data} // Set the rows to be displayed pages={this.state.pages} // Display the total number of pages loading={this.state.loading} // Display the loading overlay when we need it diff --git a/stories/SubComponents.js b/stories/SubComponents.js index 163c5e7..1e9833a 100644 --- a/stories/SubComponents.js +++ b/stories/SubComponents.js @@ -26,7 +26,7 @@ class Story extends React.Component { collapseOnPageChange: true, collapseOnDataChange: true, freezeWhenExpanded: false, - showFilters: false, + filterable: false, sortable: true, resizable: true },