new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

shadcn/ui · Components · all subjects

data-table/usage

28 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Selected rows counter example

Example of displaying selected row count: <div className="flex-1 text-sm text-muted-foreground"> {table.getFilteredSelectedRowModel().rows.length} of{" "} {table.getFilteredRowModel().rows.length} row(s) selected. </div>

Data Table prerequisites - Payment data type

The Payment type for data table examples has the following structure: id (string), amount (number), status (enum: 'pending' | 'processing' | 'success' | 'failed'), and email (string).

TanStack Table v9 features configuration

TanStack Table v9 is feature-based. Register features using tableFeatures() to declare which behavior to enable. Unregistered features are tree-shaken from the bundle. Register features: columnFilteringFeature, columnVisibilityFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature. Register row models: createFilteredRowModel(), createPaginatedRowModel(), createSortedRowModel(). Register filter functions under filterFns (e.g., includesString for email filtering) and sort functions under sortFns (e.g., text and alphanumeric). The core row model is always included automatically.

Column definition with accessor and display

Use createColumnHelper to define columns. Use columnHelper.accessor() for data columns that map to row properties. Use columnHelper.display() for columns without data binding. Example: columnHelper.accessor('email', { header: 'Email' }) defines a sortable/filterable email column.

Basic DataTable component

The DataTable component renders table rows using table.getRowModel().rows. It uses Table, TableHeader, TableHead, TableBody, TableCell, and TableRow components. TableHeader renders table.getFlatHeaders() with header.id and isRowHeader set to true for the first header. TableBody renders visible cells from each row with table.FlexRender for flexible cell content rendering.

Basic DataTable component example

'use client' import { useTable, type ColumnDef, type RowData } from '@tanstack/react-table' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' import { features, type DataTableFeatures } from './data-table-features' interface DataTableProps<TData extends RowData> { columns: ColumnDef<DataTableFeatures, TData>[] data: TData[] } export function DataTable<TData extends RowData>({ columns, data, }: DataTableProps<TData>) { const table = useTable({ features, data, columns, }) return ( <div className="overflow-hidden rounded-md border"> <Table> <TableHeader> {table.getFlatHeaders().map((header) => ( <TableHead key={header.id} id={header.id} isRowHeader={header.index === 0} > {header.isPlaceholder ? null : ( <table.FlexRender header={header} /> )} </TableHead> ))} </TableHeader> <TableBody renderEmptyState={() => 'No results.'}> {table.getRowModel().rows.map((row) => ( <TableRow key={row.id} id={row.id}> {row.getVisibleCells().map((cell) => ( <TableCell key={cell.id}> <table.FlexRender cell={cell} /> </TableCell> ))} </TableRow> ))} </TableBody> </Table> </div> ) }

Row actions dropdown example

Example of adding actions column in columns.tsx: columnHelper.display({ id: 'actions', cell: ({ row }) => { const payment = row.original return ( <DropdownMenuTrigger> <Button variant="ghost" size="icon-xs"> <span className="sr-only">Open menu</span> <MoreHorizontal /> </Button> <DropdownMenu placement="bottom end" className="w-44"> <DropdownMenuGroup> <DropdownMenuLabel>Actions</DropdownMenuLabel> <DropdownMenuItem onClick={() => navigator.clipboard.writeText(payment.id)} > Copy payment ID </DropdownMenuItem> </DropdownMenuGroup> <DropdownMenuSeparator /> <DropdownMenuGroup> <DropdownMenuItem>View customer</DropdownMenuItem> <DropdownMenuItem>View payment details</DropdownMenuItem> </DropdownMenuGroup> </DropdownMenu> </DropdownMenuTrigger> ) }, })

Pagination in data tables

Pagination is automatically enabled when rowPaginationFeature and createPaginatedRowModel() are registered in the features object. By default, tables paginate into pages of 10 rows. Add pagination controls using table.previousPage() and table.nextPage() methods with disabled state based on table.getCanPreviousPage() and table.getCanNextPage().

Pagination controls example

Example of adding pagination controls to DataTable: import { Button } from '@/components/ui/button' export function DataTable<TData extends RowData>({ columns, data, }: DataTableProps<TData>) { const table = useTable({ features, data, columns, }) return ( <div> <div className="overflow-hidden rounded-md border"> <Table>{ ... }</Table> </div> <div className="flex items-center justify-end space-x-2 py-4"> <Button variant="outline" size="sm" onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()} > Previous </Button> <Button variant="outline" size="sm" onClick={() => table.nextPage()} disabled={!table.getCanNextPage()} > Next </Button> </div> </div> ) }

Sorting in data tables

Sorting is enabled when rowSortingFeature and createSortedRowModel() are registered in the features object. Wire up sorting by managing SortingState in component state and passing onSortingChange and state.sorting to useTable. Pass sortDescriptor and onSortChange props to the Table component. Make header cells sortable by rendering column headers with sorting controls.

Sorting implementation example

Example of implementing sorting in DataTable: import * as React from 'react' import { useTable, type SortingState } from '@tanstack/react-table' export function DataTable<TData extends RowData>({ columns, data, }: DataTableProps<TData>) { const [sorting, setSorting] = React.useState<SortingState>([]) const table = useTable({ features, data, columns, onSortingChange: setSorting, state: { sorting }, }) return ( <div> <div className="overflow-hidden rounded-md border"> <Table sortDescriptor={ sorting.length ? { column: sorting[0].id, direction: sorting[0].desc ? 'descending' : 'ascending', } : undefined } onSortChange={(sortDescriptor) => { table.setSorting([ { id: '' + sortDescriptor.column, desc: sortDescriptor.direction === 'descending', }, ]) }} > { ... } </Table> </div> </div> ) }

Sortable column header

Make a column header sortable by wrapping it with buttonVariants({ variant: 'ghost' }) and adding a sort icon. The table automatically handles ascending/descending sorting when the header is clicked.

Sortable header example

Example of making email column sortable in columns.tsx: import { ArrowUpDown } from 'lucide-react' import { buttonVariants } from '@/components/ui/button' columnHelper.accessor('email', { header: ({ column }) => { return ( <div className={buttonVariants({ variant: 'ghost' })}> Email <ArrowUpDown className="ml-2 h-4 w-4" /> </div> ) }, })

Filtering in data tables

Filtering is enabled when columnFilteringFeature and createFilteredRowModel() are registered in the features object. Wire up filtering by managing ColumnFiltersState in component state and passing onColumnFiltersChange and state.columnFilters to useTable. Add an Input component to set filter values using table.getColumn('columnId').setFilterValue().

Filtering implementation example

Example of implementing filtering in DataTable: import * as React from 'react' import { useTable, type ColumnFiltersState } from '@tanstack/react-table' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' export function DataTable<TData extends RowData>({ columns, data, }: DataTableProps<TData>) { const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]) const table = useTable({ features, data, columns, onColumnFiltersChange: setColumnFilters, state: { columnFilters }, }) return ( <div> <div className="flex items-center py-4"> <Input placeholder="Filter emails..." value={(table.getColumn('email')?.getFilterValue() as string) ?? ''} onChange={(event) => table.getColumn('email')?.setFilterValue(event.target.value) } className="max-w-sm" /> </div> <div className="overflow-hidden rounded-md border"> <Table>{ ... }</Table> </div> </div> ) }

Column visibility in data tables

Column visibility is enabled when columnVisibilityFeature is registered in the features object. Wire up visibility by managing ColumnVisibilityState in component state and passing onColumnVisibilityChange and state.columnVisibility to useTable. Add a dropdown menu with DropdownMenuCheckboxItem to toggle visibility of individual columns.

Column visibility implementation example

Example of implementing column visibility in DataTable: import * as React from 'react' import { useTable, type ColumnVisibilityState } from '@tanstack/react-table' import { Button } from '@/components/ui/button' import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' export function DataTable<TData extends RowData>({ columns, data, }: DataTableProps<TData>) { const [columnVisibility, setColumnVisibility] = React.useState<ColumnVisibilityState>({}) const table = useTable({ features, data, columns, onColumnVisibilityChange: setColumnVisibility, state: { columnVisibility }, }) return ( <div> <div className="flex items-center py-4"> <DropdownMenuTrigger> <Button variant="outline" className="ml-auto"> Columns </Button> <DropdownMenu placement="bottom end"> <DropdownMenuGroup selectionMode="multiple" selectedKeys={ table .getVisibleFlatColumns() .filter((column) => column.getCanHide()) .map(column => column.id) } onSelectionChange={(keys) => { table.setColumnVisibility( Object.fromEntries( table .getAllFlatColumns() .map((c) => [ c.id, !c.getCanHide() || keys === 'all' || keys.has(c.id), ]) ) ) }} > {table .getAllColumns() .filter((column) => column.getCanHide()) .map((column) => ( <DropdownMenuItem key={column.id} id={column.id} className="capitalize" > {column.id} </DropdownMenuItem> ))} </DropdownMenuGroup> </DropdownMenu> </DropdownMenuTrigger> </div> <div className="overflow-hidden rounded-md border"> <Table>{ ... }</Table> </div> </div> ) }

Row selection in data tables

Row selection is enabled when rowSelectionFeature is registered in the features object. Add a select column using columnHelper.display() with id 'select' containing Checkbox components with slot='selection'. Wire up selection by managing row selection state with onRowSelectionChange and state.rowSelection in useTable. Pass selectionMode='multiple' and selectedKeys to the Table component.

Row selection column example

Example of adding select column in columns.tsx: import { Checkbox } from '@/components/ui/checkbox' columnHelper.display({ id: 'select', header: () => <Checkbox slot="selection" />, cell: () => <Checkbox slot="selection" />, enableSorting: false, enableHiding: false, })

Row selection implementation example

Example of implementing row selection in DataTable: export function DataTable<TData extends RowData>({ columns, data, }: DataTableProps<TData>) { const [rowSelection, setRowSelection] = React.useState({}) const table = useTable({ features, data, columns, onRowSelectionChange: setRowSelection, state: { rowSelection }, }) return ( <div> <div className="overflow-hidden rounded-md border"> <Table selectionMode="multiple" selectedKeys={table.getSelectedRowModel().rows.map((row) => row.id)} onSelectionChange={(selection) => { if (selection === 'all') { table.toggleAllRowsSelected() } else { table.setRowSelection( Object.fromEntries([...selection].map((key) => [key, true])) ) } }} /> </div> </div> ) }

Cell formatting example

To format cells, update the column definition's cell property. For example, to format a currency amount: cell: ({ row }) => { const amount = parseFloat(row.getValue('amount')); const formatted = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); return <div className='text-right font-medium'>{formatted}</div> }

Row actions using dropdown menu

Add row actions by creating a display column with columnHelper.display(). Access row data with row.original. Render a dropdown menu with DropdownMenuTrigger containing a Button, and DropdownMenuContent with DropdownMenuItems for actions.

Pagination setup in DataTable

Pagination is automatically enabled when rowPaginationFeature and createPaginatedRowModel() are included in the features object. Default page size is 10. Add pagination controls using table.previousPage() and table.nextPage() methods with table.getCanPreviousPage() and table.getCanNextPage() to check if pagination is available.

Sorting setup in DataTable

To enable sorting, import SortingState from @tanstack/react-table. Create state with React.useState<SortingState>([]). Pass onSortingChange and sorting state to useTable. In column definitions, create a sortable header by calling column.toggleSorting(column.getIsSorted() === 'asc') on click.

Filtering setup in DataTable

To enable filtering, import ColumnFiltersState from @tanstack/react-table. Create state with React.useState<ColumnFiltersState>([]). Pass onColumnFiltersChange and columnFilters state to useTable. Render an Input that gets/sets filter value using table.getColumn('columnName')?.getFilterValue() and table.getColumn('columnName')?.setFilterValue().

Column visibility toggle in DataTable

To enable column visibility toggling, import ColumnVisibilityState from @tanstack/react-table. Create state with React.useState<ColumnVisibilityState>({}). Pass onColumnVisibilityChange and columnVisibility state to useTable. Render a dropdown menu with DropdownMenuCheckboxItems for each column from table.getAllColumns().filter(column => column.getCanHide()). Use column.getIsVisible() to check visibility and column.toggleVisibility() to toggle.

Row selection setup in DataTable

To enable row selection, add a display column with checkboxes in both header and cell. In header: checkbox checked={table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate')} onChange triggers table.toggleAllPageRowsSelected(). In cell: checkbox checked={row.getIsSelected()} onChange triggers row.toggleSelected(). Create state with useState({}) and pass onRowSelectionChange and rowSelection to useTable.

Accessing row data in column definitions

Access row data using row.original in the cell function of a column definition. This can be used to handle row actions like making API calls with the row's id.

Give your agent this brain