Column Groups
Span a header across several columns, and nest those spans as deep as your data does. Add columnGroupShow to a child and the group becomes collapsible — a compact summary when closed, the detail columns when open.
Nesting — a header row per level
Three levels: Employee over Identity and Contact, Employment over Compensation. The grid renders one header row per level of nesting and works out every span for you. Scroll sideways and watch a group's label stay with it.
A group is any object with a children array, and [columns] takes a mix
of those and ordinary leaf columns. A child may itself be a group, which is all nesting is:
{ name: 'Employee', children: [
{ name: 'Identity', children: [ …First name, Surname… ] },
{ name: 'Contact', children: [ …Email, Phone… ] },
] }
One header row per level. This grid is three deep, so the header is three rows
tall — two rows of spanners and the leaf row. Every span is counted for you from the shape of the
array; there is no colspan to keep in sync. The # column is in no group and still
occupies its own cell in each of the rows above it.
A group label stays with its group while you scroll. Scroll the body sideways and
Employment stays pinned at the leading edge for as long as any of its columns is still on
screen, then leaves with the last of them. That is stickyLabel, on by default; set it
to false on a group and the label scrolls off with its first column.
Drag a group's trailing edge and every column inside it resizes at once. The
delta is shared out proportionally, and each child still stops at its own
minWidth/maxWidth. Individual columns keep their own handles. Set
resizable: false on the group to lock the group-level edge alone.
Collapsible — columnGroupShow
Employment starts open and Contact starts closed. Press either chevron: the 'open' children appear, the 'closed' summary swaps out, and a width you dragged first is still there when it comes back.
A group becomes collapsible the moment one of its children carries a
columnGroupShow — a chevron appears on the spanner and the group starts answering to
it. There are three values, and the third is the default:
'open'— on screen only while the group is expanded. The detail: Salary, Bonus and Start date here.'closed'— on screen only while the group is collapsed. The summary that stands in for the detail: Status here.'everywhere', or leaving it out — always on screen. Department here, which is why the group never vanishes entirely.
A collapsible group starts open. openByDefault defaults to
true, so Employment needs no line at all; Contact carries
openByDefault: false, and that is the entire difference between the two on this page.
Contact shows only Phone until you open it, because Email is its one
'open' child.
A collapsible group needs at least one column that survives each state — a
'closed' child or one with no columnGroupShow at all. A group whose
children are all 'open' would have nothing left once it closed, and its
spanner would go with them: no chevron, and nothing left to click to bring it back. The mirror
case is a group whose children are all 'closed', which would be missing before you
touched anything.
So the grid does not offer the toggle at all in either case: the group renders as a plain
spanner with every child visible, and a development-mode console message names the group and
what to add. A toggle you must not press is not a toggle. That is also why Contact's Phone
column carries no columnGroupShow — it is the child that makes Contact genuinely
collapsible.
Widths survive a collapse. Drag Salary wider, collapse Employment, expand it again: the width you set is still there. Hidden children are hidden, not rebuilt, so nothing the reader has adjusted is thrown away.
Sorting, filtering and resizing behave on a grouped leaf exactly as they do on an ungrouped one. Grouping is a header arrangement, and it changes nothing below the header.
What a group is
[columns] accepts ColumnOrGroup<T>[] — leaf columns, groups, or
both in any order. A group is an object with a children array and a
name for its spanner label; a child can be another group, so the nesting goes as deep
as your data does. Every header row and every span is derived from that one array.
Nothing about a group reaches the rows. Cells, sorting, filtering, editing and export all see the leaf columns exactly as they would if the groups were not there — which is why grouping can be added to an existing grid without touching anything else.
Collapsible groups
columnGroupShow on a child is what makes its parent collapsible.
Give at least one child 'open' or 'closed' and a chevron appears on the
spanner; leave every child without it and the group is a static header.
'open'— shown while the group is expanded.'closed'— shown while the group is collapsed. The usual use is one compact summary column standing in for several detail ones.'everywhere'or unset — always shown.
openByDefault is true unless you say otherwise, so a collapsible
group starts expanded and openByDefault: false is the line that starts one closed. A
nested group can carry its own columnGroupShow as well, and then it appears
or disappears with its parent's state.
Always leave a collapsible group something to show in each state — a
'closed' child, or one with no columnGroupShow at all. A group's spanner
is drawn over its visible columns, so a group whose children are all 'open'
would lose its header along with them the moment it collapsed. Rather than let that happen, the
grid declines the toggle: no chevron, every child visible, and a dev-mode console message naming
the group. The same applies to all-'closed' children, which would be missing while
the group is open.
Resizing a group
With config.columnResize on, a group's trailing header edge is a resize handle for
every visible column inside it: the delta is distributed proportionally and each child is clamped
to its own minWidth/maxWidth. A child with resizable: false
keeps its width and is left out of the distribution. Set resizable: false on the
group to lock only the group-level edge — the children keep their own handles.
Keeping a group together
marryChildren: true asks the grid to keep a group's columns adjacent while the reader
drags one of them, so a reorder cannot leave a hole in the middle of a group. It is best-effort
rather than a hard lock.
The label while scrolling
A group wider than the viewport would otherwise lose its label off the leading edge, so by default
the label is pinned there (after any pinned columns) for as long as one of the group's columns is
visible. stickyLabel: false turns that off per group.
columnGroupShow: 'closed' is the half people forget. A group that only hides
columns reads as a disappearing act; a group that swaps three detail columns for one summary
column reads as a level of zoom.
Column group options
| Property | Type | Default | Description |
|---|---|---|---|
| group.children | ColumnOrGroup<T>[] | — | Any object with children renders as a spanning header. A child may be another group, so nesting has no ceiling — one header row is rendered per level. |
| group.name / headerName | string | — | The spanner label. headerName is an alias; name wins if both are set. |
| group.openByDefault | boolean | true | Whether a collapsible group starts expanded. Set false to start it closed. |
| column.columnGroupShow | 'open' | 'closed' | 'everywhere' | 'everywhere' | Declared on a CHILD, and what makes the parent collapsible. 'open' shows while expanded, 'closed' while collapsed, unset always. |
| group.columnGroupShow | 'open' | 'closed' | 'everywhere' | 'everywhere' | The same option on a nested group — it appears or disappears with its parent group's state. |
| group.resizable | boolean | true | Drag the group edge to resize every visible child at once, proportionally and clamped per child (needs config.columnResize). Set false to lock only the group-level edge. |
| group.stickyLabel | boolean | true | Keep the label pinned at the leading edge while the group is scrolled horizontally, until its last column leaves. Set false to let it scroll away with the first column. |
| group.marryChildren | boolean | false | Best-effort: keeps the group's columns adjacent while the reader drag-reorders one of them. |
| group.headerClass | string | — | CSS class on the group spanner cell — for colouring or spacing a band of related columns. |
| group.headerTooltip | string | () => string | null | the group name | Text for the spanner's tooltip. A group header already shows its own name unconditionally; set this only to say something different. See Tooltips. |
| group.headerGroupTemplate | TemplateRef<HeaderGroupContext> | — | Custom spanner content. The context carries name, open and collapsible. See Templates. |