Is there an API to invoke the filter function of each (or some) of the columns from outside the table?
We want to have a search box outside of the table and to be able to enter values. Like for example:
To search the first and last name in the searchbox:

(of course we don't have such simple columns that can be merged)
There is no API for this in ReactTable.
Only two choices (well three):
The third option is to use a different package if the other options are not suitable.
The following is a very basic example of the first option:
Great example, it works perfectly with what I need. And I think you can create truly hidden filter column by adding below to All column.
getProps: () => ({ style: { padding: "0px" } }),
getHeaderProps: () => ({ style: { padding: 0 } }),
Closing due to issue age. If this issue was a question, please ask it again on https://spectrum.chat/react-table. If you think this issue needs to be reopened or if it should be turned into a pull-request, please check the latest version of React-Table for the issue or feature once more and reopen or create a PR if appropriate. Thanks!
There is no API for this in ReactTable.
Only two choices (well three):
- do what I think you were hinting at and create a "hidden" (width zero) column and filter on that
- filter the data externally (if it is so complex - then your filter logic will be complex and can't possibly be done by a generic table tool like ReactTable) and the just update your ReactTable data state with the filtered data
The third option is to use a different package if the other options are not suitable.
The following is a very basic example of the first option:
Is it possible that even the column is invisible, the column can still be filtered?
Yes, that's possible in v6 :)
My solution:
I created decorator(HOC) for my table and implemented search logic in decorator.
/* eslint-disable react/prop-types */
import React, { Component } from 'react'
const tableDecorator = (Table) => class WrappedTable extends Component {
constructor(props) {
super(props)
this.state = {
term: '',
}
this.methods = {
filterCaseInsensitive: ::this.filterCaseInsensitive,
filterFunction: ::this.filterFunction,
onSearchChange: ::this.onSearchChange,
}
const { columns } = props
this.columns = columns.map((c) => { // getting column names
const {
id,
accessor,
} = c
return typeof accessor === 'string' ? accessor : id
})
}
onSearchChange(term) {
this.setState({ term })
}
/* used for filtering data in withSearchField mode */
/* Common function for filtering each column in each row. */
filterFunction(row) {
let res = false
const { term } = this.state
for(let i = 0; i < this.columns.length; i += 1) {
const val = row[this.columns[i]]
if(!Array.isArray(val)) {
if(String(val).toLowerCase().includes(term.toLowerCase())) {
res = true
break
}
} else {
for(let j = 0; i < val.length; j += 1) {
if(String(val[j]).toLowerCase().includes(term.toLowerCase())) {
res = true
break
}
}
}
}
return res
}
filterCaseInsensitive(filter, row) {
const id = filter.pivotId || filter.id
return (
row[id] !== undefined
? String(row[id].toString().toLowerCase()).startsWith(filter.value.toLowerCase())
: true
)
}
render() {
const {
withSearchField,
} = this.props
let {
data,
} = this.props
if(withSearchField) { // if withSearchField prop is true then we filter data
data = data.filter(this.methods.filterFunction)
}
return (
<Table
{...this.props}
{...this.methods}
data={data}
/>
)
}
}
export default tableDecorator
**Next i implemented stupid component with table mark up.**
import React, { Fragment } from 'react'
import ReactTable from 'react-table'
import { defaultProps, propTypes } from './tablePropTypes'
import tableDecorator from './tableDecorator'
import './TableBlank.scss'
import TextBox from '../TextBox'
const TableBlank = ({
data,
columns,
resizable,
loading,
defaultPageSize,
filterCaseInsensitive,
withSearchField,
onSearchChange,
term,
}) => (
<Fragment>
{
withSearchField &&
<div className="table-up-div">
<div className="table-filter-field">
<TextBox
value={term}
placeholder="Search"
onChange={onSearchChange}
/>
</div>
</div>
}
<ReactTable
data={data}
columns={columns}
resizable={resizable}
loading={loading}
defaultPageSize={defaultPageSize}
className="-highlight"
defaultFilterMethod={filterCaseInsensitive}
/>
</Fragment>
)
TableBlank.defaultProps = defaultProps
TableBlank.propTypes = propTypes
export default tableDecorator(TableBlank)
md5-4fd40fd056a989b2cf973fbd57c9a2d4
import Table from '../Table' // import decorated table
...
in render
<Table
columns={this.state.columns}
loading={this.state.loading}
data={this.state.usersList}
withSearchField // pass this param=true if you want show table with search field.
/>
My solution:
I created decorator(HOC) for my table and implemented search logic in decorator./* eslint-disable react/prop-types */ import React, { Component } from 'react' const tableDecorator = (Table) => class WrappedTable extends Component { constructor(props) { super(props) this.state = { term: '', } this.methods = { filterCaseInsensitive: ::this.filterCaseInsensitive, filterFunction: ::this.filterFunction, onSearchChange: ::this.onSearchChange, } const { columns } = props this.columns = columns.map((c) => { // getting column names const { id, accessor, } = c return typeof accessor === 'string' ? accessor : id }) } onSearchChange(term) { this.setState({ term }) } /* used for filtering data in withSearchField mode */ /* Common function for filtering each column in each row. */ filterFunction(row) { let res = false const { term } = this.state for(let i = 0; i < this.columns.length; i += 1) { const val = row[this.columns[i]] if(!Array.isArray(val)) { if(String(val).toLowerCase().includes(term.toLowerCase())) { res = true break } } else { for(let j = 0; i < val.length; j += 1) { if(String(val[j]).toLowerCase().includes(term.toLowerCase())) { res = true break } } } } return res } filterCaseInsensitive(filter, row) { const id = filter.pivotId || filter.id return ( row[id] !== undefined ? String(row[id].toString().toLowerCase()).startsWith(filter.value.toLowerCase()) : true ) } render() { const { withSearchField, } = this.props let { data, } = this.props if(withSearchField) { // if withSearchField prop is true then we filter data data = data.filter(this.methods.filterFunction) } return ( <Table {...this.props} {...this.methods} data={data} /> ) } } export default tableDecorator**Next i implemented stupid component with table mark up.** import React, { Fragment } from 'react' import ReactTable from 'react-table' import { defaultProps, propTypes } from './tablePropTypes' import tableDecorator from './tableDecorator' import './TableBlank.scss' import TextBox from '../TextBox' const TableBlank = ({ data, columns, resizable, loading, defaultPageSize, filterCaseInsensitive, withSearchField, onSearchChange, term, }) => ( <Fragment> { withSearchField && <div className="table-up-div"> <div className="table-filter-field"> <TextBox value={term} placeholder="Search" onChange={onSearchChange} /> </div> </div> } <ReactTable data={data} columns={columns} resizable={resizable} loading={loading} defaultPageSize={defaultPageSize} className="-highlight" defaultFilterMethod={filterCaseInsensitive} /> </Fragment> ) TableBlank.defaultProps = defaultProps TableBlank.propTypes = propTypes export default tableDecorator(TableBlank)Feel free to use your own instead of my component.
How to use:import Table from '../Table' // import decorated table ... in render <Table columns={this.state.columns} loading={this.state.loading} data={this.state.usersList} withSearchField // pass this param=true if you want show table with search field. />
Why dont you create a library out of that? Have a generic impl, so that everyone wont have to going through defining one on their own?
How would you do this using useTable in version 7?
I've gone with just working my custom filters into the useMemo call which provides the data to the table. If there's a "more correct" way I'd like to hear about it.
Please see #1527
In my particular case I'm not looking to filter on all columns in a standardized way, rather just a subset of columns and in some cases I'd almost certainly need custom logic.
I see. In that case, then you can easily just keep using useMemo on your table data before it enters the table.
Most helpful comment
There is no API for this in ReactTable.
Only two choices (well three):
The third option is to use a different package if the other options are not suitable.
The following is a very basic example of the first option:
https://codesandbox.io/s/r74mokr5x4