Given a table of budget line items, I would like to group them by year where each year grouping should display the year and the aggregate amount of the line items as in this screenshot: example datatable with custom grouping rows
Is it possible to get the "grouping row" to render differently from the detail rows so that it can match the screenshot?
This is a minimal reproduction of what I've been able to figure out:
import { useState } from "react";
import {
ColumnDef,
useReactTable,
getCoreRowModel,
flexRender,
getGroupedRowModel,
getExpandedRowModel,
} from "@tanstack/react-table";
type Asset = {
name: string;
year: number;
amount: number;
};
export function App() {
const columns: ColumnDef<Asset>[] = [
{
accessorKey: "name",
header: "Name",
},
{
accessorKey: "year",
header: "Year",
},
{
accessorKey: "amount",
header: "Amount",
aggregationFn: "sum",
},
];
const [data, setData] = useState([
{ name: "Item 1", year: 2022, amount: 31 },
{ name: "Item 2", year: 2022, amount: 4312 },
{ name: "Item 3", year: 2022, amount: 1233 },
{ name: "Item 4", year: 2024, amount: 123 },
{ name: "Item 5", year: 2024, amount: 512 },
]);
const table = useReactTable({
columns,
data,
getCoreRowModel: getCoreRowModel(),
getGroupedRowModel: getGroupedRowModel(),
getExpandedRowModel: getExpandedRowModel(),
state: {
grouping: ["year"],
},
});
return (
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>
{cell.getIsPlaceholder()
? null
: flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
);
}
Yes. The cell
object includes methods such as getIsGrouped()
and getIsAggregated()
that you can use to style and or display as desired.
Here is an example of adding tailwind classNames to the td
:
<td
key={cell.id}
className={
cell.getIsGrouped() ? "bg-red-50" :
cell.getIsAggregated() ? "bg-orange-50" :
cell.getIsPlaceholder() ? "bg-blue-50" :
""}
>
{cell.getIsPlaceholder()
? null
: flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
The same methods can be used to decide how to render the content inside the td as well—for example to add a count to the end of the value display.
An example can be found here: https://tanstack.com/table/v8/docs/examples/react/grouping