Filters (Client-side)
The following example demonstrates clientside filters for a table with 100,000 rows of data.
First Name | Last Name | Username | Visit Count | Role | Account Status |
|---|
import {useMemo, useState} from "react"
import {Search} from "lucide-react"
import {
type ColumnDef,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
} from "@qualcomm-ui/core/table"
import {Button} from "@qualcomm-ui/react/button"
import {Pagination} from "@qualcomm-ui/react/pagination"
import {Popover} from "@qualcomm-ui/react/popover"
import {ProgressRing} from "@qualcomm-ui/react/progress-ring"
import {
flexRender,
Table,
useReactTable,
useTablePagination,
} from "@qualcomm-ui/react/table"
import {TextInput} from "@qualcomm-ui/react/text-input"
import {useDebounce} from "@qualcomm-ui/react-core/effects"
import {TableColumnFilter} from "./filters"
import {type User, type UserColumnMeta, useUserData} from "./use-data"
export function FiltersClientSideDemo() {
const {data = [], isFetching, refetch} = useUserData(100000)
// always memoize your data and columns
const userColumns: ColumnDef<User, any, UserColumnMeta>[] = useMemo(
() => [
{
accessorKey: "firstName",
header: "First Name",
id: "firstName",
meta: {filterLabel: "First Name"},
},
{
accessorKey: "lastName",
header: "Last Name",
id: "lastName",
meta: {filterLabel: "Last Name"},
},
{
accessorKey: "username",
header: "Username",
id: "username",
meta: {filterLabel: "Username"},
},
{
accessorKey: "visitCount",
header: "Visit Count",
id: "visitCount",
meta: {filterLabel: "Visit Count"},
},
{
accessorKey: "role",
header: "Role",
id: "role",
meta: {filterLabel: "Role"},
},
{
accessorKey: "accountStatus",
header: "Account Status",
id: "accountStatus",
meta: {filterLabel: "Account Status"},
},
],
[],
)
const [globalFilter, setGlobalFilter] = useState("")
const refreshData = () => refetch()
// Debounce the global filter for better performance. Registering on every
// keystroke causes lag for the first few keys, as fewer characters can match the
// majority of the table's data.
const debouncedGlobalFilter = useDebounce(globalFilter, 150)
const table = useReactTable<User>({
columns: userColumns,
data,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
state: {
globalFilter: debouncedGlobalFilter,
},
})
const paginationProps = useTablePagination(table)
return (
<div className="flex w-full flex-col gap-4 p-2">
<Table.Root>
<Table.ActionBar>
<TextInput
className="w-56"
onValueChange={setGlobalFilter}
placeholder="Search every column..."
size="sm"
startIcon={Search}
value={globalFilter}
/>
<Button
onClick={() => void refreshData()}
size="sm"
variant="outline"
>
Refresh Data
</Button>
{isFetching ? <ProgressRing size="xs" /> : null}
</Table.ActionBar>
<Table.ScrollContainer>
<Table.Table>
<Table.Header>
{table.getHeaderGroups().map((headerGroup) => (
<Table.Row key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<Table.HeaderCell
key={header.id}
colSpan={header.colSpan}
>
{header.isPlaceholder ? null : (
<div className="inline-flex w-full items-center justify-between gap-2">
{flexRender(
header.column.columnDef.header,
header.getContext(),
)}
{header.column.getCanFilter() ? (
<Popover
trigger={
<Table.ColumnFilterAction
canFilter={header.column.getCanFilter()}
isFiltered={header.column.getIsFiltered()}
/>
}
>
<TableColumnFilter
column={header.column}
table={table}
/>
</Popover>
) : null}
</div>
)}
</Table.HeaderCell>
)
})}
</Table.Row>
))}
</Table.Header>
<Table.Body>
{table.getRowModel().rows.map((row) => {
return (
<Table.Row key={row.id}>
{row.getVisibleCells().map((cell) => {
return (
<Table.Cell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</Table.Cell>
)
})}
</Table.Row>
)
})}
</Table.Body>
</Table.Table>
</Table.ScrollContainer>
<Table.Pagination {...paginationProps}>
<Pagination.PageMetadata>
{({count, pageEnd, pageStart}) => (
<>
{pageStart}-{pageEnd} of {count} results
</>
)}
</Pagination.PageMetadata>
<Pagination.PageButtons />
</Table.Pagination>
</Table.Root>
<Button
onClick={() =>
console.info(
"table.getSelectedRowModel().flatRows",
table.getSelectedRowModel().flatRows,
)
}
variant="outline"
>
Log table.getSelectedRowModel().flatRows
</Button>
</div>
)
}