Custom Filter Tanstack/React Table

166 Views Asked by At

I'm trying to filter a list of objects by a filter object:

condition: {
    "WHERE",
    "AND",
    "OR"
}

id: {
    "firstName",
    "lastName",
    "birth",
}

operator: {
    "contains",
    "does not contain",
    "equals",
    "does not equal"
}

value: ""

where the user is able to select one of the options from every dropdown. Ex. of a filter object:

[
  {
    condition: 'WHERE', id: 'firstName', operator: "does not contain", value: "f"
  },
  {
    condition: 'AND', id: 'lastName', operator: "does not contain", value: "d"
  }
]

So in a list of people:

[
  {
    firstName: 'foo', lastName: "bar"
  },
  {
    firstName: 'john', lastName: "doe"
  },
  {
    firstName: 'rick', lastName: "roll"
  }
]

I should only get returned Rick Roll. But it doesn't seem to work.

  const table = useReactTable({
    data: people,
    columns: tableColumns,
    filterFns: filterData,
    enableFilters: true,
    state: {
      sorting: sort,
      columnFilters: filters,
      grouping: groupState,
      columnVisibility
    },
    onColumnFiltersChange: updateFilter,
    onGroupingChange: setGroupState,
    onSortingChange: setSort,
    onColumnVisibilityChange: setColumnVisibility,
    getExpandedRowModel: getExpandedRowModel(),
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getGroupedRowModel: getGroupedRowModel()
  });
function filterData(data) {
    return data.filter((item) => {
      let result = true;
      filters.forEach((filter) => {
        let fieldValue = item[filter.id.toLowerCase().replace(/\s/g, '_')];
        let condition = false;
        switch (filter.operator) {
          case 'Contains':
            condition = fieldValue.toLowerCase().includes(filter.value.toLowerCase());
            break;
          case 'Does not contain':
            condition = !fieldValue.toLowerCase().includes(filter.value.toLowerCase());
            break;
          case 'Starts with':
            condition = fieldValue.toLowerCase().startsWith(filter.value.toLowerCase());
            break;
          case 'Ends with':
            condition = fieldValue.toLowerCase().endsWith(filter.value.toLowerCase());
            break;
          case 'Equals':
            condition = fieldValue === filter.value;
            break;
          case 'Does not equal':
            condition = fieldValue !== filter.value;
            break;
          case 'Is empty':
            condition = fieldValue === '';
            break;
          case 'Is not empty':
            condition = fieldValue !== '';
            break;
          default:
            condition = true;
        }
        if (filter.condition === 'AND') {
          result = result && condition;
        } else if (filter.condition === 'OR') {
          result = result || condition;
        }
      });
      return result;
    });
  }

I've tried looking at all the docs, but none explicitly show custom functions. Sometimes the filter works, other times the condition provides the inverse. Am I missing something?

0

There are 0 best solutions below