@tanstack/table-core
Version:
Headless UI for building powerful tables & datagrids for TS/JS.
138 lines (106 loc) • 4.76 kB
Markdown
name: aggregation
description: >
Aggregate TanStack Table columns independently of grouping, including grand totals, caller-selected row totals, multiple keyed aggregations, custom context-based definitions, grouped merges, manual values, and worker constraints.
metadata:
{ type: sub-skill, library: '@tanstack/table-core', library_version: '9.0.0' }
requires: ['core', 'table-features']
sources:
- 'TanStack/table:docs/guide/aggregation.md'
- 'TanStack/table:docs/framework/react/guide/aggregation.md'
- 'TanStack/table:packages/table-core/src/features/row-aggregation'
- 'TanStack/table:examples/react/aggregation'
- 'TanStack/table:examples/react/grouped-aggregation'
This skill builds on `core` and `table-features`. Aggregation is independent
from grouping: use it alone for totals, or combine it with the `grouping` skill
for synthetic grouped rows.
## Setup
<!-- skill-snippet:check -->
```ts
import {
rowAggregationFeature,
aggregationFn_mean,
aggregationFn_sum,
tableFeatures,
} from '@tanstack/table-core'
export const features = tableFeatures({
rowAggregationFeature,
aggregationFns: {
mean: aggregationFn_mean,
sum: aggregationFn_sum,
},
})
```
## Core Patterns
### Grand total and selected row scopes
```ts
const grandTotal = salaryColumn.getAggregationValue()
const filteredTotal = salaryColumn.getAggregationValue({
rows: table.getFilteredRowModel().rows,
})
const childTotal = salaryColumn.getAggregationValue({
rows: table.getCoreRowModel().rows,
maxDepth: 1,
})
```
The default uses the pre-grouped row model. Explicit rows can come from any row
model or caller-selected subset. `maxAggregationDepth` defaults to `0`, which
selects the supplied roots; `1` selects direct sub-rows, and `Infinity` selects
terminal rows. Branches that end early contribute their deepest available row.
Default calls are cached; explicit-row calls intentionally are not because array
identity and contents are caller-owned. `table.getMaxSubRowDepth()` returns the
deepest structural depth in the core row model.
### Multiple aggregations
```ts
columnHelper.accessor('salary', {
aggregationFn: ['mean', { id: 'range', aggregationFn: 'extent' }],
})
const value = salaryColumn.getAggregationValue<{
mean: number
range: [number, number]
}>()
```
A scalar option returns a scalar. An array returns a keyed object. Named
functions use their registry name; descriptors provide a stable `id`, which is
required for inline definitions in an array.
### Custom definitions
```ts
const weightedMean = constructAggregationFn({
aggregate: ({ rows, getValue }) => {
const total = rows.reduce((sum, row) => sum + Number(getValue(row)), 0)
return rows.length ? total / rows.length : undefined
},
})
```
The context provides depth-selected `rows`, `maxDepth`, `getValue`, `column`,
`columnId`, `table`, and optional grouped-only `groupingRow` and `subRows`.
Every aggregation configured on a column receives the same row frontier. Add
`merge({ subRowResults, subRows, ...context })` when nested groups can more
efficiently combine already-computed sub-row results; otherwise the engine calls
`aggregate` with both row sets. `subRowResults[i]` corresponds to `subRows[i]`.
### Manual or remote values
Set a column definition's `getAggregationValue(context)` to return `{ value }`
for requests handled by a server or another execution environment. Returning
`undefined` falls back to the local definition. `manualAggregation: true`
disables that local fallback.
## Common Mistakes
### [HIGH] Adding grouping for a grand total
Wrong: registering `columnGroupingFeature` solely to total a column.
Correct: register `rowAggregationFeature` and call
`column.getAggregationValue()`. Grouping is only required for grouped rows.
### [HIGH] Passing a scope label and rows
There is no scope option. Call `getAggregationValue()` for the cached default,
or pass a single options object containing rows from the desired row model and
`maxDepth` when the desired frontier is below those rows.
### [HIGH] Reusing the legacy callable signature
Wrong: `(columnId, leafRows, childRows) => result`.
Correct: `constructAggregationFn({ aggregate: ({ rows, subRows, getValue }) => result })`.
### [MEDIUM] Assuming arbitrary totals run in the worker
The experimental worker computes grouped row-model aggregates. Public
`getAggregationValue(options?)` totals execute on the main thread, and custom
grouped results sent by the worker must be structured-cloneable.
## API Discovery
Inspect `node_modules/@tanstack/table-core/dist/features/row-aggregation/` and the
Aggregation Guide. Use `Column_RowAggregation`, `AggregationFnDef`,
`AggregationContext`, and `AggregationResult` for the typed public surface.