Group aggregators
When grouping is active, each group row can show a rolled-up value per column -
the sum of revenue, the average score, the count of deals. SvGrid does this
declaratively: set aggregate on a column and the group header shows the
result, formatted with that column's own format.
Open the live example: Group aggregators (Sorting & Grouping)
Every example on this page runs against these rows:
<script lang="ts">
import { SvGrid, tableFeatures, columnGroupingFeature, type ColumnDef } from '@svgrid/grid'
type Row = { region: string; rep: string; revenue: number; winRate: number }
const data: Row[] = [
{ region: 'EMEA', rep: 'Ada', revenue: 82_000, winRate: 0.42 },
{ region: 'EMEA', rep: 'Linus', revenue: 61_500, winRate: 0.31 },
{ region: 'Americas', rep: 'Grace', revenue: 94_200, winRate: 0.55 },
{ region: 'Americas', rep: 'Alan', revenue: 47_800, winRate: 0.28 },
{ region: 'APAC', rep: 'Mei', revenue: 73_400, winRate: 0.47 },
]
const features = tableFeatures({ columnGroupingFeature })
const columns: ColumnDef<typeof features, Row>[] = [
{ field: 'region', header: 'Region' },
{ field: 'rep', header: 'Rep' },
{ field: 'revenue', header: 'Revenue', format: { type: 'currency', currency: 'USD' } },
{ field: 'winRate', header: 'Win rate', format: { type: 'percent' } },
]
</script>
<script lang="ts">
import { SvGrid, tableFeatures, columnGroupingFeature, type ColumnDef } from '@svgrid/grid'
const features = tableFeatures({ columnGroupingFeature })
const columns: ColumnDef<typeof features, Row>[] = [
{ field: 'region', header: 'Region' },
{ field: 'revenue', header: 'Revenue', aggregate: 'sum', format: { type: 'currency', currency: 'USD' } },
{ field: 'winRate', header: 'Win rate', aggregate: 'avg', format: { type: 'percent' } },
]
</script>
<SvGrid {data} {columns} {features} groupable />
Built-in reducers
aggregate |
Result |
|---|---|
'sum' |
Sum of the finite numeric values. |
'avg' |
Mean of the finite numeric values. |
'min' / 'max' |
Smallest / largest value. |
'count' |
Number of leaf rows in the group. |
'countDistinct' |
Number of distinct values. |
'extent' |
"min – max" range string. |
'first' |
The first leaf row's value (e.g. a shared label). |
Non-numeric and empty cells are ignored by the numeric reducers; an all-empty group yields no value (the header chip is hidden).
Custom aggregators
Pass a function for anything the built-ins don't cover - weighted average, median, percentile, distinct-with-rules. It receives the finite numeric values and the raw leaf rows:
const median = (vals: number[]) =>
vals.length ? [...vals].sort((a, b) => a - b)[Math.floor(vals.length / 2)] : 0
const columns = [
{ field: 'score', header: 'Median score', aggregate: median },
// weighted average using two columns off the raw rows:
{
field: 'rate',
header: 'Blended rate',
aggregate: (_vals, rows: Row[]) => {
const w = rows.reduce((s, r) => s + r.weight, 0)
return w ? rows.reduce((s, r) => s + r.rate * r.weight, 0) / w : 0
},
},
]
The footer summary row
The same reducers drive the grid's footer row, which totals the whole filtered
set rather than a group. It is off by default - turn it on with summary:
<SvGrid {data} {columns} summary />
Out of the box each column falls back to a sensible guess: the sum of a numeric
column, Count: N otherwise. Give a column its own summary to choose, using
the reducer names from the table above:
<script lang="ts">
const columns: ColumnDef<typeof features, Row>[] = [
{ field: 'region', header: 'Region' },
{ field: 'revenue', header: 'Revenue', summary: 'sum', format: { type: 'currency', currency: 'USD' } },
{ field: 'winRate', header: 'Win rate', summary: 'avg', format: { type: 'percent' } },
// Nothing worth totalling in this one.
{ id: 'actions', header: '', summary: false },
]
</script>
<SvGrid {data} {columns} summary />
summary is independent of aggregate: one feeds the footer, the other feeds
group rows, and a column can set both to different reducers. enableRowSummaries
is the long-form name for the grid prop; summary wins when both are set.
Notes
- Aggregates roll up all leaf rows under a group, at every nesting level.
- The aggregated value is stored on the group row, so
api.getDisplayedRows()androw.getCellValueByColumnId(id)return it too - handy for exporting group totals. - The reducer is exported as
applyGroupAggregate(agg, columnId, rows)for reuse outside the grid.
See the live Group aggregators demo.
Related articles
- Building a Project / Task Board with a Svelte Data Grid - How to build a task management grid with grouping by status or assignee, inline edits, subtask tree rows, and saved views - without reaching for a dedicated project management tool.
- Multi-Level (Grouped) Column Headers in SvGrid - Band related columns under a shared parent header using SvGrid's nested column definition - how to nest, pin, combine with sorting and filtering, and when NOT to use grouping.
- Inside SvGrid: Grouping, Trees, and Master-Detail - Three different ways to show hierarchy in a data grid, unified under one expansion model in SvGrid - the design decision and how each feature actually works.