bo-grid v3.1.0

Columns

.md

Computed columns

Derive a column's value from the whole row, such as a total, a ratio or a P&L, and sort, filter, total and export it like any other column.

A computed column derives its value from the row instead of reading a field. Give the column a value(row) function: the result is shown, sorted, filtered, totalled, formatted conditionally, copied and exported exactly like a stored value. Use it for KPIs, ratios and deltas you would otherwise have to precompute and keep in sync.

Value and P&L below exist on no row; sort by either, and see the footer total them:

computed-columns.svelte GitHub ↗

Defining one

const columns: ColumnDef[] = [
  { type: 'number', key: 'qty', header: 'Qty', decimals: 0 },
  { type: 'price', key: 'last', header: 'Last' },
  // No `value` field on the rows: derived, and still sortable and exportable.
  { type: 'number', key: 'value', header: 'Value', decimals: 0, groupAgg: 'sum', value: (r) => Number(r.qty) * Number(r.last) },
];
  • key still names the column: sorting, filtering, hiding and saved layouts refer to it. It does not have to be a real field on the row.
  • The column’s type formats the result, so a computed price uses type: 'price'.
  • groupAgg totals it on group rows and in the grid’s footer.

Rules

  • Keep it cheap and pure. value() runs while sorting and filtering, not only when a cell draws. Read the row and return a value; don’t fetch or mutate anything.
  • It is read-only. There is no field to write an edit back to, so computed columns are not editable.
  • In memory only. With a server data source, the server computes its own derived fields.

Reference

Column options from the types
value (row: GridRow) => unknown

Computed value: derive this cell's value from the whole row instead of reading row[key] (KPIs, ratios, deltas). Flows through display, sort, filter, aggregation, export and conditional formatting. key still names the column (and is the sort/filter key) but need not be a real row field. Keep it cheap and pure — it's called during sort/filter. Computed columns aren't editable. In-memory mode (a server source owns its own derivations).

Example
{ type: 'percent', key: 'chg', header: 'Chg %', value: (row) => ((Number(row.last) - Number(row.ref)) / Number(row.ref)) * 100 }
groupAgg AggKind Default undefined

When grouping is active (or with footer), show this aggregate of the column on group headers and the totals row.

Example
{ type: 'volume', key: 'qty', header: 'Qty', groupAgg: 'sum' }
format (value: unknown, row?: GridRow) => string

Custom display formatter, overriding the built-in type formatter. Applies to display, tooltip, copy and (formatted) export. row is absent for aggregate cells.

Example
{ type: 'number', key: 'qty', header: 'Qty', format: (v) => Number(v).toLocaleString('vi-VN') }
Grid props from the types
footer boolean Default false

Show a pinned totals row: each column with a groupAgg shows that aggregate over all (filtered) rows. In-memory mode only.