From 5dce30ea08349ae3a4b2053e9d5a1ae5f5c25730 Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Fri, 17 Jul 2026 19:28:28 -0500 Subject: [PATCH] fix(table-core): honor explicit global filter opt-in --- .../globalFilteringFeature.ts | 7 +++++ .../createFilteredRowModel.test.ts | 28 +++++++++++++++++++ .../globalFilteringFeature.utils.test.ts | 23 +++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/packages/table-core/src/features/global-filtering/globalFilteringFeature.ts b/packages/table-core/src/features/global-filtering/globalFilteringFeature.ts index ef4f630c02..ea182fe0cb 100644 --- a/packages/table-core/src/features/global-filtering/globalFilteringFeature.ts +++ b/packages/table-core/src/features/global-filtering/globalFilteringFeature.ts @@ -28,6 +28,13 @@ export const globalFilteringFeature: TableFeature = { onGlobalFilterChange: makeStateUpdater('globalFilter', table), globalFilterFn: 'auto', getColumnCanGlobalFilter: (column) => { + if ( + 'enableGlobalFilter' in column.columnDef && + column.columnDef.enableGlobalFilter === true + ) { + return true + } + const value = table .getCoreRowModel() .flatRows[0]?.getAllCellsByColumnId() diff --git a/packages/table-core/tests/implementation/features/column-filtering/createFilteredRowModel.test.ts b/packages/table-core/tests/implementation/features/column-filtering/createFilteredRowModel.test.ts index 455a34f509..2c9cefc1bb 100644 --- a/packages/table-core/tests/implementation/features/column-filtering/createFilteredRowModel.test.ts +++ b/packages/table-core/tests/implementation/features/column-filtering/createFilteredRowModel.test.ts @@ -479,6 +479,34 @@ describe('createFilteredRowModel', () => { }) describe('global filtering edge cases', () => { + it('should globally filter an object-valued column that explicitly opts in', () => { + interface ObjectValueRow { + value: { label: string } + } + + const table = constructTable({ + features, + columns: [ + { + accessorKey: 'value', + id: 'value', + enableGlobalFilter: true, + }, + ], + data: [{ value: { label: 'keep' } }, { value: { label: 'drop' } }], + globalFilterFn: (row, _columnId, filterValue) => + row.original.value.label.includes(String(filterValue)), + initialState: { + globalFilter: 'keep', + }, + }) + + expect(table.getFilteredRowModel().rows).toHaveLength(1) + expect(table.getFilteredRowModel().rows[0]!.original.value.label).toBe( + 'keep', + ) + }) + it('should pass rows through when no columns are globally filterable', () => { const table = constructTable({ features, diff --git a/packages/table-core/tests/unit/features/global-filtering/globalFilteringFeature.utils.test.ts b/packages/table-core/tests/unit/features/global-filtering/globalFilteringFeature.utils.test.ts index debd05def2..43188fc14d 100644 --- a/packages/table-core/tests/unit/features/global-filtering/globalFilteringFeature.utils.test.ts +++ b/packages/table-core/tests/unit/features/global-filtering/globalFilteringFeature.utils.test.ts @@ -71,6 +71,15 @@ describe('column_getCanGlobalFilter', () => { expect(column_getCanGlobalFilter(table.getColumn('active')!)).toBe(false) }) + it('should allow non-string, non-number values to explicitly opt in', () => { + const filterColumns: Array> = [ + { accessorKey: 'active', id: 'active', enableGlobalFilter: true }, + ] + const table = constructTable({ features, data, columns: filterColumns }) + + expect(column_getCanGlobalFilter(table.getColumn('active')!)).toBe(true) + }) + it('should return false for display columns without an accessor', () => { const table = makeTable() @@ -106,6 +115,20 @@ describe('column_getCanGlobalFilter', () => { expect(column_getCanGlobalFilter(table.getColumn('firstName')!)).toBe(false) expect(column_getCanGlobalFilter(table.getColumn('age')!)).toBe(true) }) + + it('should let a custom predicate reject an explicit column opt-in', () => { + const filterColumns: Array> = [ + { accessorKey: 'active', id: 'active', enableGlobalFilter: true }, + ] + const table = constructTable({ + features, + data, + columns: filterColumns, + getColumnCanGlobalFilter: () => false, + }) + + expect(column_getCanGlobalFilter(table.getColumn('active')!)).toBe(false) + }) }) describe('table_getGlobalAutoFilterFn', () => {