Add disableGlobalFilter prop to allow for columns (and instance) to ignore global filter (#1963)

* size-snapshot created?

* Added `disableGlobalFilter` prop and associated tests

* Updated documentation

* improvement(useglobalfilter): add `disableGlobalFilter` prop

Adding `disableGlobalFilter` prop to both table and column to allow columns to be excluded from
Global Filter

* test(usefilters.test.js): added base test for disableGlobalFilter

Needed a test to make sure that disableGlobalFilter didn't break anything when applied

* Delete .size-snapshot.json

* Update README.md

Co-authored-by: Jason Clark <jason.clark@tcnbroadcasting.com>
Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
This commit is contained in:
Jason Clark 2020-03-06 14:49:00 -08:00 committed by GitHub
parent 63754a58dd
commit 512f615988
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 186 additions and 9 deletions

View File

@ -23,6 +23,8 @@ The following options are supported via the main options object passed to `useTa
- `manualGlobalFilter: Bool`
- Enables filter detection functionality, but does not automatically perform row filtering.
- Turn this on if you wish to implement your own row filter outside of the table (eg. server-side or manual row grouping/nesting)
- `disableGlobalFilter: Bool`
- Disables global filtering for every column in the entire table.
- `filterTypes: Object<filterKey: filterType>`
- Must be **memoized**
- Allows overriding or adding additional filter types for the table to use. If the globalFilter type isn't found on this object, it will default to using the built-in filter types.
@ -34,6 +36,14 @@ The following options are supported via the main options object passed to `useTa
- To disable, set to `false`
- For more information see the FAQ ["How do I stop my table state from automatically resetting when my data changes?"](./faq#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
### Column Options
The following options are supported on any `Column` object passed to the `columns` option in `useTable()`
- `disableGlobalFilter: Bool`
- Optional
- If set to `true`, will disable global filtering for this column
### Instance Properties
The following values are provided to the table `instance`:

View File

@ -52,10 +52,14 @@ const defaultColumn = {
),
}
function App() {
function App(props) {
const [data, setData] = React.useState(makeData)
const columns = React.useMemo(
() => [
const columns = React.useMemo(() => {
if (props.columns) {
return props.columns
}
return [
{
Header: 'Name',
columns: [
@ -90,9 +94,8 @@ function App() {
},
],
},
],
[]
)
]
}, [props.columns])
const {
getTableProps,
@ -177,6 +180,8 @@ test('renders a filterable table', async () => {
const globalFilterInput = rendered.getByPlaceholderText('Global search...')
const filterInputs = rendered.getAllByPlaceholderText('Search...')
expect(filterInputs).toHaveLength(6)
fireEvent.change(filterInputs[1], { target: { value: 'l' } })
expect(
rendered
@ -243,3 +248,146 @@ test('renders a filterable table', async () => {
'firstName: jaylen',
])
})
test('does not filter columns marked as disableFilters', () => {
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
disableFilters: true,
},
{
Header: 'Last Name',
accessor: 'lastName',
disableFilters: true,
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
]
const rendered = render(<App columns={columns} />)
const filterInputs = rendered.getAllByPlaceholderText('Search...')
expect(filterInputs).toHaveLength(4)
// should be Age column
fireEvent.change(filterInputs[0], { target: { value: '45' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual(['firstName: joe'])
fireEvent.change(filterInputs[0], { target: { value: '' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual([
'firstName: tanner',
'firstName: derek',
'firstName: joe',
'firstName: jaylen',
])
})
test('does not filter columns with GlobalFilter if marked disableGlobalFilter', () => {
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
disableGlobalFilter: true,
},
{
Header: 'Last Name',
accessor: 'lastName',
disableGlobalFilter: true,
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
]
const rendered = render(<App columns={columns} />)
const globalFilterInput = rendered.getByPlaceholderText('Global search...')
fireEvent.change(globalFilterInput, { target: { value: '' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual([
'firstName: tanner',
'firstName: derek',
'firstName: joe',
'firstName: jaylen',
])
// global filter shouldn't apply to firstName or lastName
fireEvent.change(globalFilterInput, { target: { value: 'li' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual(['firstName: joe'])
// double check global filter ignore (should ignore joe bergevin)
fireEvent.change(globalFilterInput, { target: { value: 'in' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual(['firstName: tanner', 'firstName: derek', 'firstName: jaylen'])
})

View File

@ -1,6 +1,10 @@
import React from 'react'
import { getFilterMethod, shouldAutoRemoveFilter } from '../utils'
import {
getFilterMethod,
shouldAutoRemoveFilter,
getFirstDefined,
} from '../utils'
import {
actions,
@ -68,6 +72,7 @@ function useInstance(instance) {
state: { globalFilter: globalFilterValue },
dispatch,
autoResetGlobalFilter = true,
disableGlobalFilter,
} = instance
const setGlobalFilter = React.useCallback(
@ -105,11 +110,23 @@ function useInstance(instance) {
return rows
}
allColumns.forEach(column => {
const { disableGlobalFilter: columnDisableGlobalFilter } = column
column.canFilter = getFirstDefined(
columnDisableGlobalFilter === true ? false : undefined,
disableGlobalFilter === true ? false : undefined,
true
)
})
const filterableColumns = allColumns.filter(c => c.canFilter === true)
// Filters top level and nested rows
const filterRows = filteredRows => {
filteredRows = filterMethod(
filteredRows,
allColumns.map(d => d.id),
filterableColumns.map(d => d.id),
globalFilterValue
)
@ -132,10 +149,11 @@ function useInstance(instance) {
globalFilterValue,
globalFilter,
userFilterTypes,
allColumns,
rows,
flatRows,
rowsById,
allColumns,
disableGlobalFilter,
])
const getAutoResetGlobalFilter = useGetLatest(autoResetGlobalFilter)
@ -157,5 +175,6 @@ function useInstance(instance) {
flatRows: globalFilteredFlatRows,
rowsById: globalFilteredRowsById,
setGlobalFilter,
disableGlobalFilter,
})
}