Skege
Skege

Reputation: 111

How to set up a custom filtering in ReactTable?

How do I set filtering? I have created one column and passed it to ReactTable component. Next I created a filtering function that I use inside wanted columns.

const columns = [{
    Header: 'Brand',
    accessor: 'brand',
    Cell: props => editableCell(props),
    Filter: selectColumnFilter,
    filter: 'includes'
}]

const selectColumnFilter = props => {
    const options = data.cars.filter((car, i) => {
        return i === data.cars.findIndex(obj => {
            return car[props.column.id] === obj[props.column.id];
        })
    }); // Gets the requested option values
    
    return <select onChange={e => {console.log(e.target.value)}}>
        <option value="">All</option>
        {options.map((option, i) => <option key={i} value={option[props.column.id]}>{option[props.column.id]}</option>)}
    </select> // Prints the select
}

Inside of selectColumnFilter function I pass the column info as props argument. From the props object I fetch the id and filter cars array

return <ReactTable
    ref={(r) => setReactTable(r)}
    data={data.cars} 
    columns={columns} 
    filterable={filterable}
    pages={pages}
    loading={loading}
    defaultPageSize={pageSize}
    className="-striped -highlight"
/>

Now I only need to figure out how to set the value as "filtering" and then update the table view.

Upvotes: 1

Views: 10221

Answers (2)

Skege
Skege

Reputation: 111

Finally just figured it out.

Filter passes props object to custom filter (in this case selectColumnFilter).

All I had to do was attach props's onChange method to returned element (in this case select element)

const selectColumnFilter = props => {
    const options = data.cars.filter((car, i) => {
      return i === data.cars.findIndex(obj => {
        return car[props.column.id] === obj[props.column.id];
    })
  });
        
  // attach the onChange method from props's object to element
  return <select onChange={(e) => props.onChange(e.target.value)}>
    <option value="">All</option>
    {options.map((option, i) => <option key={i} value={option[props.column.id]}> 
    {option[props.column.id]}</option>)}
  </select>
}

Remember to pass the element's value to the onChange method otherwise your table doesn't get filtered and updated.

Upvotes: 2

Chris Nguyen
Chris Nguyen

Reputation: 2900

I don't know where is the data comes from but you can try this:

function SelectColumnFilter({
  column: { filterValue, setFilter, preFilteredRows, id },
}) {
  // Calculate the options for filtering
  // using the preFilteredRows
  const options = React.useMemo(() => {
    const options = new Set()
    preFilteredRows.forEach(row => {
      options.add(row.values[id])
    })
    return [...options.values()]
  }, [id, preFilteredRows])

  // Render a multi-select box
  return (
    <select
      value={filterValue}
      onChange={e => {
        // this line will set filter value
        setFilter(e.target.value || undefined) 
      }}
    >
      <option value="">All</option>
      {options.map((option, i) => (
        <option key={i} value={option}>
          {option}
        </option>
      ))}
    </select>
  )
}

Upvotes: 0

Related Questions