1
votes

I am trying to implement checkbox filters for a Material Ui table using React hooks. My goal is to map over an array of filter values, and filter the table data if the row object matches the any of the filtered value.

For example if I select/check 2 filter values, I want to compare the filter values to the respective row object property, and add the row data to a new array if the property matches one of the filter values.

Below is my progress.

Table.js


 // Set state using useState hook
 const [filter, setFilter] = React.useState(null);

 // Table data
 tableData = [
   {color: 'red', type:'fruit', name:'apple'},
   {color: 'blue', type:'fruit', name:'blueberry'},
   {color: 'green', type:'veg', name:'lettuce'},
   {color: 'green', type:'veg', name:'celery'},
 ]

 // Pull unique colors from global state
 const uniqueColors = [...new Set(arr.map(item => item.color))]; // [red, blue, green]

 // Handle checkbox filtering ... this is where I'm running into issues
 function handleSelectFilter(option, checked) {
    if(checked){
      setFilter(option); // add option to filter array
      let filterArr = tableData.filter(row => row.color == option);
    }else{
      //if unchecked, remove from filterArr and unfilter the table
      let filterArr = tableData.filter(row => row.color !== option);
      setFilter(filterArr);
    }
  }

  ...

  return (
   ...
    <Grid>
     <FilterPopOver 
      options={uniqueColors}
      onSelectFilter={handleSelectFilter}
     />
    </Grid>
   ...
)

FilterPopover.js: onChange -- the FilterPopover component just sends handleSelectFilter() the value that was changed, and if it was checked or unchecked (e.g., (red, true))

Desired Output

 filterArr=['red','green']

 tableData = [
   {color: 'red', type:'fruit', name:'apple'},
   {color: 'green', type:'veg', name:'lettuce'},
   {color: 'green', type:'veg', name:'celery'},
 ]
1

1 Answers

1
votes

You can use includes() method to check if an item's color is present in the selected filters array.

Live Example:

var tableData = [
   {color: 'red', type:'fruit', name:'apple'},
   {color: 'blue', type:'fruit', name:'blueberry'},
   {color: 'green', type:'veg', name:'lettuce'},
   {color: 'green', type:'veg', name:'celery'},
 ];
 
function filterData(tableData, filters) {
  return tableData.filter(item => filters.includes(item.color));
}

console.log(filterData(tableData, ['red', 'green']));

From your question, it is not clear what setFilter() does, but you could do as shown below:

function handleSelectFilter(option, checked) {
  if(checked) {
    // Add option to filter array.
    this.filterArr.push(option);
  } else {
    // Remove option from filter array.
    this.filterArr = this.filterArr.filter(color => color !== option);
  }

  // Filter table data.
  this.tableData = this.tableData.filter(item => filterArr.includes(item.color));
}