T
TanStack2y ago
wise-white

Filter Reset

Can I detect when a filter has been reset via
table.resetColumnFilters()
table.resetColumnFilters()
This is my ColumnDef
{
accessorKey: "depot",
filterFn: (
rows: Row<Vehicle>,
_headerName: string,
getFilterValue: string[]
) => {
return getFilterValue.includes(rows.original.depot);
},
header: ({ table, column }) => {
return (
<HeaderFilter
table={table}
column={column}
title={"Depot"}
filterOptions={["Haydock", "Haydock 2", "Leeds", "Tyne and Wear"]}
/>
);
}
{
accessorKey: "depot",
filterFn: (
rows: Row<Vehicle>,
_headerName: string,
getFilterValue: string[]
) => {
return getFilterValue.includes(rows.original.depot);
},
header: ({ table, column }) => {
return (
<HeaderFilter
table={table}
column={column}
title={"Depot"}
filterOptions={["Haydock", "Haydock 2", "Leeds", "Tyne and Wear"]}
/>
);
}
I need to reset the state of my filterOptions (array of options). Any ideas?
3 Replies
wise-white
wise-whiteOP2y ago
If more code is needed I can provide it, just not sure about rules of posting lots of code.
export default function HeaderFilter<TData>(props: propsInterface<TData>) {
const { column, title, filterOptions } = props;
const [open, setOpen] = useState<boolean>(false);
const [selectedFilters, setSelectedFilters] = useState<string[]>(
filterOptions || []
);

const handleFilterChange = (option: string) => {
if (selectedFilters.includes(option)) {
const filters = selectedFilters;
filters.splice(selectedFilters.indexOf(option), 1);
setSelectedFilters(filters);
column.setFilterValue(filters);
} else {
const filters = [...selectedFilters, option]
setSelectedFilters(filters);
column.setFilterValue(filters);
}
};

return (
<div className="flex justify-between items-center">
{filterOptions && (
<DropdownMenu open={open} onOpenChange={() => setOpen(!open)}>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="h-4 w-4 rounded-sm"
onClick={() => setOpen(true)}
>
<MoreVertical />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[150px]">
<DropdownMenuLabel>Filter Columns</DropdownMenuLabel>
<DropdownMenuSeparator />
{filterOptions.map((option) => (
<DropdownMenuCheckboxItem
key={option}
checked={selectedFilters.includes(option)}
onClick={() => handleFilterChange(option)}
>
{option}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)}
</div>
);
}
export default function HeaderFilter<TData>(props: propsInterface<TData>) {
const { column, title, filterOptions } = props;
const [open, setOpen] = useState<boolean>(false);
const [selectedFilters, setSelectedFilters] = useState<string[]>(
filterOptions || []
);

const handleFilterChange = (option: string) => {
if (selectedFilters.includes(option)) {
const filters = selectedFilters;
filters.splice(selectedFilters.indexOf(option), 1);
setSelectedFilters(filters);
column.setFilterValue(filters);
} else {
const filters = [...selectedFilters, option]
setSelectedFilters(filters);
column.setFilterValue(filters);
}
};

return (
<div className="flex justify-between items-center">
{filterOptions && (
<DropdownMenu open={open} onOpenChange={() => setOpen(!open)}>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="h-4 w-4 rounded-sm"
onClick={() => setOpen(true)}
>
<MoreVertical />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[150px]">
<DropdownMenuLabel>Filter Columns</DropdownMenuLabel>
<DropdownMenuSeparator />
{filterOptions.map((option) => (
<DropdownMenuCheckboxItem
key={option}
checked={selectedFilters.includes(option)}
onClick={() => handleFilterChange(option)}
>
{option}
</DropdownMenuCheckboxItem>
))}
</DropdownMenuContent>
</DropdownMenu>
)}
</div>
);
}
I think ive managed to fix it, added
resetFilters={column.getFilterValue() ? false : true}
resetFilters={column.getFilterValue() ? false : true}
to the header and then
useEffect(() => {
if (resetFilters && filterOptions) {
setSelectedFilters(filterOptions);
}
}, [resetFilters, filterOptions]);
useEffect(() => {
if (resetFilters && filterOptions) {
setSelectedFilters(filterOptions);
}
}, [resetFilters, filterOptions]);
in the headerfilter component. Not sure if this is the best way and someone has a better way?
environmental-rose
environmental-rose2y ago
Not sure if this helps, but you can also check in a useEffect for the length of columnFilters this way:
useEffect(() => {
if (table.getState().columnFilters.length === 0) {
console.log("Reset!");
}
}, [table.getState().columnFilters]);
useEffect(() => {
if (table.getState().columnFilters.length === 0) {
console.log("Reset!");
}
}, [table.getState().columnFilters]);
Note, it doesn't specifically detect when the method resetColumnFilters has been called, but rather the abscence of any type of filter.
robust-apricot
robust-apricot2y ago
Without reading much of the above, it sounds like you're attempting to handle some user triggered event, without treating it like a user triggered event, which is generally why you reach for useEffect, in the hope that it'll solve your problem. But it won't. To take control of the filters you need to handle the resets and updates via user triggered updates to the state that you control. This does not require a useEffect.

Did you find this page helpful?