mirror of
https://github.com/vxcontrol/pentagi.git
synced 2026-08-23 03:26:37 +00:00
fix(frontend): refilter DataTable when search columns change
The first implementation routed the active-column set through TanStack's `getColumnCanGlobalFilter` predicate and tried to nudge the pipeline with `table.setGlobalFilter((current) => current)`. TanStack treats that as a no-op because the resolved value equals the current state, so the filter pipeline never re-ran after the user narrowed the picker — the table kept matching against the previous column set. Bake the active set into per-column `enableGlobalFilter` via a memoised `tanstackColumns` instead. TanStack sees a new columns reference whenever the user's selection changes and refilters automatically, which is the standard mechanism for this kind of dynamic filter and verified end-to-end in the browser on the Flows list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
8ccc2db3cb
commit
d4c1b1342e
@@ -396,24 +396,29 @@ function DataTable<TData, TValue = unknown>({
|
||||
|
||||
// Active column set for the global filter: when the user has narrowed via
|
||||
// the picker, honour the explicit list; otherwise fall back to all
|
||||
// candidates ("empty selection = search everywhere"). Recomputed on each
|
||||
// render — cheap because it's just a couple of arrays — and consumed by
|
||||
// the closure below.
|
||||
const getColumnCanGlobalFilter = useCallback(
|
||||
(column: Column<TData, unknown>) => {
|
||||
const active = searchColumns.length > 0 ? searchColumns : searchCandidateIds;
|
||||
// candidates ("empty selection = search everywhere"). Bake the predicate
|
||||
// into per-column `enableGlobalFilter` so TanStack re-evaluates the row
|
||||
// model whenever the set changes — a `getColumnCanGlobalFilter` closure
|
||||
// alone would update silently because `state.globalFilter` stays equal.
|
||||
const tanstackColumns = useMemo<ColumnDef<TData, TValue>[]>(() => {
|
||||
const active = searchColumns.length > 0 ? searchColumns : searchCandidateIds;
|
||||
|
||||
return active.includes(column.id);
|
||||
},
|
||||
[searchCandidateIds, searchColumns],
|
||||
);
|
||||
return columns.map((column) => {
|
||||
const withId = column as { id?: string };
|
||||
const withAccessor = column as { accessorKey?: string };
|
||||
const columnId =
|
||||
withId.id ?? (typeof withAccessor.accessorKey === 'string' ? withAccessor.accessorKey : undefined);
|
||||
const enableGlobalFilter = typeof columnId === 'string' && active.includes(columnId);
|
||||
|
||||
return { ...column, enableGlobalFilter };
|
||||
});
|
||||
}, [columns, searchCandidateIds, searchColumns]);
|
||||
|
||||
const table = useReactTable({
|
||||
autoResetPageIndex: false,
|
||||
columns,
|
||||
columns: tanstackColumns,
|
||||
data,
|
||||
enableSortingRemoval: true,
|
||||
getColumnCanGlobalFilter,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
@@ -436,22 +441,6 @@ function DataTable<TData, TValue = unknown>({
|
||||
},
|
||||
});
|
||||
|
||||
// TanStack doesn't re-run the filter pipeline when only the
|
||||
// `getColumnCanGlobalFilter` predicate's closure changes — it watches
|
||||
// `state.globalFilter`. Re-set the same value through TanStack's API on
|
||||
// every `searchColumns` change so the pipeline picks up the new predicate.
|
||||
// Skip the very first render to avoid a redundant cycle on mount.
|
||||
const isFirstRefilterRender = useRef(true);
|
||||
useEffect(() => {
|
||||
if (isFirstRefilterRender.current) {
|
||||
isFirstRefilterRender.current = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
table.setGlobalFilter((current: string) => current);
|
||||
}, [searchColumns, table]);
|
||||
|
||||
const handleRowClick = useCallback(
|
||||
(row: Row<TData>) => {
|
||||
if (onRowClick) {
|
||||
|
||||
Reference in New Issue
Block a user