Skip to content

Commit c0fd539

Browse files
committed
fix: use getFilteredRowModel when filtering is enabled
1 parent 8974f75 commit c0fd539

3 files changed

Lines changed: 148 additions & 0 deletions

File tree

src/components/Table/__stories__/Table.stories.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {Meta, StoryObj} from '@storybook/react';
33
import {Table} from '../index';
44

55
import {DefaultStory} from './stories/DefaultStory';
6+
import {FilteringStory} from './stories/FilteringStory';
67
import {GroupingStory} from './stories/GroupingStory';
78
import {GroupingWithSelectionStory} from './stories/GroupingWithSelectionStory';
89
import {ReorderingStory} from './stories/ReorderingStory';
@@ -62,6 +63,10 @@ export const Sorting: StoryObj<typeof SortingStory> = {
6263
render: SortingStory,
6364
};
6465

66+
export const Filtering: StoryObj<typeof FilteringStory> = {
67+
render: FilteringStory,
68+
};
69+
6570
export const Reordering: StoryObj<typeof ReorderingStory> = {
6671
render: ReorderingStory,
6772
};
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import * as React from 'react';
2+
3+
import {Select, TextInput} from '@gravity-ui/uikit';
4+
import type {SelectOption} from '@gravity-ui/uikit';
5+
import type {ColumnDef, ColumnFiltersState} from '@tanstack/react-table';
6+
7+
import {useTable} from '../../../../hooks';
8+
import type {Item} from '../../../BaseTable/__stories__/types';
9+
import {Table} from '../../Table';
10+
11+
const filterableData: Item[] = [
12+
{id: '1', name: 'John Doe', age: 23, status: 'free'},
13+
{id: '2', name: 'Jane Smith', age: 27, status: 'busy'},
14+
{id: '3', name: 'Bob Johnson', age: 22, status: 'free'},
15+
{id: '4', name: 'Alice Brown', age: 21, status: 'unknown'},
16+
{id: '5', name: 'Mike Wasowsky', age: 28, status: 'busy'},
17+
{id: '6', name: 'Sarah Connor', age: 25, status: 'free'},
18+
{id: '7', name: 'Tom Hardy', age: 30, status: 'busy'},
19+
{id: '8', name: 'Emma Watson', age: 24, status: 'unknown'},
20+
{id: '9', name: 'Chris Evans', age: 26, status: 'free'},
21+
{id: '10', name: 'Scarlett Johansson', age: 29, status: 'busy'},
22+
];
23+
24+
const statusOptions: SelectOption[] = [
25+
{value: '', content: 'All'},
26+
{value: 'free', content: 'Free'},
27+
{value: 'busy', content: 'Busy'},
28+
{value: 'unknown', content: 'Unknown'},
29+
];
30+
31+
const filterableColumns: ColumnDef<Item>[] = [
32+
{
33+
id: 'name',
34+
header: ({column}) => (
35+
<div>
36+
<div style={{marginBottom: '8px', fontWeight: 'bold'}}>Name</div>
37+
<TextInput
38+
value={(column.getFilterValue() as string) || ''}
39+
onUpdate={(value) => column.setFilterValue(value)}
40+
placeholder="Filter by name..."
41+
size="s"
42+
/>
43+
</div>
44+
),
45+
accessorKey: 'name',
46+
filterFn: 'includesString',
47+
size: 200,
48+
},
49+
{
50+
id: 'age',
51+
header: 'Age',
52+
accessorKey: 'age',
53+
size: 100,
54+
},
55+
{
56+
id: 'status',
57+
header: ({column}) => (
58+
<div>
59+
<div style={{marginBottom: '8px', fontWeight: 'bold'}}>Status</div>
60+
<Select
61+
value={[(column.getFilterValue() as string) || '']}
62+
onUpdate={(values) => column.setFilterValue(values[0] || undefined)}
63+
options={statusOptions}
64+
size="s"
65+
width="max"
66+
/>
67+
</div>
68+
),
69+
accessorKey: 'status',
70+
filterFn: (row, columnId, filterValue) => {
71+
if (!filterValue) return true;
72+
return row.getValue(columnId) === filterValue;
73+
},
74+
size: 150,
75+
},
76+
];
77+
78+
export const FilteringStory = () => {
79+
const [globalFilter, setGlobalFilter] = React.useState('');
80+
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
81+
82+
const table = useTable({
83+
data: filterableData,
84+
columns: filterableColumns,
85+
enableGlobalFilter: true,
86+
enableColumnFilters: true,
87+
state: {
88+
globalFilter,
89+
columnFilters,
90+
},
91+
onGlobalFilterChange: setGlobalFilter,
92+
onColumnFiltersChange: setColumnFilters,
93+
getRowId: (row) => row.id,
94+
});
95+
96+
return (
97+
<div>
98+
<div style={{marginBottom: '16px'}}>
99+
<h3 style={{marginBottom: '8px'}}>Global Search</h3>
100+
<TextInput
101+
placeholder="Search all columns..."
102+
value={globalFilter}
103+
onUpdate={setGlobalFilter}
104+
size="m"
105+
style={{maxWidth: '400px'}}
106+
/>
107+
<div style={{marginTop: '8px', fontSize: '13px', opacity: 0.7}}>
108+
Showing {table.getFilteredRowModel().rows.length} of {filterableData.length}{' '}
109+
rows
110+
</div>
111+
</div>
112+
113+
<div style={{marginBottom: '16px'}}>
114+
<button
115+
onClick={() => {
116+
setGlobalFilter('');
117+
setColumnFilters([]);
118+
}}
119+
style={{
120+
padding: '8px 16px',
121+
border: '1px solid var(--g-color-line-generic)',
122+
borderRadius: '6px',
123+
cursor: 'pointer',
124+
backgroundColor: 'var(--g-color-base-background)',
125+
color: 'var(--g-color-text-primary)',
126+
}}
127+
>
128+
Clear All Filters
129+
</button>
130+
</div>
131+
132+
<Table table={table} />
133+
</div>
134+
);
135+
};

src/hooks/useTable.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {TableOptions} from '@tanstack/react-table';
22
import {
33
getCoreRowModel,
44
getExpandedRowModel,
5+
getFilteredRowModel,
56
getGroupedRowModel,
67
getSortedRowModel,
78
useReactTable,
@@ -19,6 +20,8 @@ export const useTable = <TData>(options: UseTableOptions<TData>) => {
1920
enableMultiRowSelection: options.enableMultiRowSelection ?? false,
2021
enableRowSelection: options.enableRowSelection ?? false,
2122
enableSorting: options.enableSorting ?? false,
23+
enableColumnFilters: options.enableColumnFilters ?? false,
24+
enableGlobalFilter: options.enableGlobalFilter ?? false,
2225
getCoreRowModel: options.getCoreRowModel ?? getCoreRowModel(),
2326
getExpandedRowModel: options.enableExpanding
2427
? (options.getExpandedRowModel ?? getExpandedRowModel())
@@ -29,8 +32,13 @@ export const useTable = <TData>(options: UseTableOptions<TData>) => {
2932
getSortedRowModel: options.enableSorting
3033
? (options.getSortedRowModel ?? getSortedRowModel())
3134
: undefined,
35+
getFilteredRowModel:
36+
options.enableColumnFilters || options.enableGlobalFilter
37+
? (options.getFilteredRowModel ?? getFilteredRowModel())
38+
: undefined,
3239
manualGrouping: options.manualGrouping ?? false,
3340
manualSorting: options.manualSorting ?? false,
41+
manualFiltering: options.manualFiltering ?? false,
3442
};
3543

3644
return useReactTable(tableOptions);

0 commit comments

Comments
 (0)