Grouping
First Name | Last Name | Age | Visits | Status | Profile Progress |
---|
Show
10
{"grouping": []}
import {useState} from "react"import {ChevronDown, ChevronRight, Combine, Ungroup} from "lucide-react"import {CodeHighlight} from "@qui/mdx-docs"import {QButton, QIconButton, QPagination, QProgressCircle} from "@qui/react"import {ColumnDef,flexRender,getCoreRowModel,getExpandedRowModel,getFilteredRowModel,getGroupedRowModel,getPaginationRowModel,GroupingState,QTable,QTbody,QTd,QTh,QThead,QTr,useReactTable,useTablePagination,} from "@qui/react-table"import {Person, usePersonData} from "~utils/data"const columns: ColumnDef<Person>[] = [{accessorKey: "firstName",cell: (info) => info.getValue(),/*** override the value used for row grouping* (otherwise, defaults to the value derived from accessorKey /* accessorFn)*/getGroupingValue: (row) => `${row.firstName} ${row.lastName}`,header: "First Name",},{accessorFn: (row) => row.lastName,cell: (info) => info.getValue(),header: "Last Name",id: "lastName",},{accessorKey: "age",aggregatedCell: ({getValue}) => Math.round(getValue<number>() * 100) / 100,aggregationFn: "median",header: "Age",},{accessorKey: "visits",aggregationFn: "sum",header: "Visits",},{accessorKey: "status",header: "Status",},{accessorKey: "progress",aggregatedCell: ({getValue}) =>`${Math.round(getValue<number>() * 100) / 100}%`,aggregationFn: "mean",cell: ({getValue}) => `${Math.round(getValue<number>() * 100) / 100}%`,header: "Profile Progress",},]export default function Grouping() {const {data = [], isFetching, refetch} = usePersonData(10000)const refreshData = () => refetch()const [grouping, setGrouping] = useState<GroupingState>([])const table = useReactTable({columns,data,getCoreRowModel: getCoreRowModel(),getExpandedRowModel: getExpandedRowModel(),getFilteredRowModel: getFilteredRowModel(),getGroupedRowModel: data.length ? getGroupedRowModel() : undefined,getPaginationRowModel: getPaginationRowModel(),onGroupingChange: setGrouping,state: {grouping,},})const paginationProps = useTablePagination(table)return (<div className="p-2"><div className="mb-3 flex items-center gap-2"><QButton onClick={refreshData} variant="outline">Refresh Data</QButton>{isFetching ? <QProgressCircle size="xs" /> : null}</div><QTable><QThead>{table.getHeaderGroups().map((headerGroup) => (<QTr key={headerGroup.id}>{headerGroup.headers.map((header) => {return (<QThkey={header.id}colSpan={header.colSpan}style={{width: header.getSize()}}>{header.isPlaceholder ? null : (<div className="flex items-center gap-1">{header.column.getCanGroup() ? (// If the header can be grouped, let's add a toggle<QIconButtondenseicon={header.column.getIsGrouped() ? Ungroup : Combine}onClick={header.column.getToggleGroupingHandler()}size="m"title={header.column.getIsGrouped() ? "Ungroup" : "Group"}/>) : null}{" "}{flexRender(header.column.columnDef.header,header.getContext(),)}</div>)}</QTh>)})}</QTr>))}</QThead><QTbody>{table.getRowModel().rows.map((row) => {return (<QTr key={row.id}>{row.getVisibleCells().map((cell) => {return (<QTdkey={cell.id}isAggregated={cell.getIsAggregated()}isGrouped={cell.getIsGrouped()}>{cell.getIsGrouped() ? (// If it's a grouped cell, add an expander and row count<div className="inline-flex items-center gap-2">{row.getCanExpand() ? (<QIconButtonicon={row.getIsExpanded() ? ChevronDown : ChevronRight}onClick={row.getToggleExpandedHandler()}size="s"/>) : null}{flexRender(cell.column.columnDef.cell,cell.getContext(),)}{" "}({row.subRows.length})</div>) : cell.getIsAggregated() ? (// If the cell is aggregated, use the Aggregated// renderer for cellflexRender(cell.column.columnDef.aggregatedCell ??cell.column.columnDef.cell,cell.getContext(),)) : cell.getIsPlaceholder() ? null : ( // For cells with repeated values, render null// Otherwise, just render the regular cellflexRender(cell.column.columnDef.cell,cell.getContext(),))}</QTd>)})}</QTr>)})}</QTbody></QTable><div className="mt-4"><QPagination{...paginationProps}renderPageMeta={(context) =>`${context.currentPage} of ${context.totalPages}`}rowsPerPageLabel="Show"rowsPerPageOptions={[10, 20, 50]}/></div><CodeHighlightclassName="mt-4 w-fit"code={JSON.stringify({grouping}, null, 2)}disableCopylanguage="json"/></div>)}