Home/Rows/Row Expansion
Rows

Row Expansion

A row opens to reveal a panel of your own markup underneath it. Two options shape it: expandMode decides whether one panel is open at a time or many, and canExpand decides which rows get a chevron at all.

expandMode — many at once, or one at a time

The same grid twice, one property apart. Open two rows in the left one and both stay open; do it in the right one and the first closes itself. Everything else about the two is identical.

Turn it off, then expand a row — the panel appears instantly instead of easing in.

expandMode: 'multi' — the default

Name
Department
Status
Nadia
Engineering
On leave
Ben
Design
Active
Yara
Engineering
Active
Karim
Data
Active
Elena
Support
Active
Walid
Security
On leave
1–6 of 12

expandMode: 'single' — an accordion

Name
Department
Status
Nadia
Engineering
On leave
Ben
Design
Active
Yara
Engineering
Active
Karim
Data
Active
Elena
Support
Active
Walid
Security
On leave
1–6 of 12

Two grids, one factory, one parameter. Everything that differs between them came out of a single line:

rowExpand: { expandMode: 'multi' | 'single', estimatedHeight: 96 }
  • 'multi' — the default. Every panel you open stays open. Use it when a reader is comparing rows, because closing one to read another loses the comparison.
  • 'single' — opening a row closes the one that was open. An accordion: the grid never grows past one panel's worth of extra height, which is what you want when the panel is tall.

The panel is your markup. <ng-template #gcExpandRow> goes inside <gridcraft> and receives an ExpandContext<T> whose $implicit is the parent row — so let-row needs no name. A card, a chart, a form, another component of yours: the grid only decides where it goes and how much height to reserve for it.

The switch above changes animateRows, not the expansion. The panel eases in over about a fifth of a second when a row opens; closing is always instant, because holding a closing panel on screen keeps the rows below it from settling. Turn the switch off and the panel simply appears. Readers who have asked their system for reduced motion never see the animation either way — that is not something you have to detect.

canExpand — only the rows that have something to show

Half of these employees have notes on file and half do not. The ones that do carry a chevron; the ones that do not render as ordinary rows, with no toggle to press and nothing to open.

Name
Department
Status
Nadia
Engineering
On leave
Ben
Design
Active
Yara
Engineering
Active
Karim
Data
Active
Elena
Support
Active
Walid
Security
On leave
Alice
Engineering
Active
Petra
Finance
Active
1–8 of 12

canExpand is a predicate over the row, and the grid asks it once per row:

rowExpand: { canExpand: row => row.notes.length > 0 }

Six of these twelve employees have notes on file. Those six carry a chevron; the other six carry nothing at all in that column — not a disabled toggle, no toggle. There is nothing to click, nothing to tab to, and nothing announced to a screen reader, which is the difference between "this row has no detail" and "this button does nothing".

Everything else about those rows is ordinary: they sort, they select, they take a cell template, and they line up with the rest. The predicate governs the toggle and nothing more.

Return true for a row whose detail you have not loaded yet — the panel is your markup, so an empty state or a spinner inside it is a perfectly good answer, and a better one than a row that cannot be opened because a request is still in flight.

What expanding a row does

config.rowExpand adds a toggle column and lets each row open a panel directly beneath it. The panel takes real vertical space: the rows below move down, the scrollbar grows, and the virtual scroller accounts for it — it is not an overlay floating over the grid.

What goes in the panel is <ng-template #gcExpandRow>, projected inside <gridcraft>. Its context is ExpandContext<T> and $implicit is the parent row, so let-row is all the binding you need.

estimatedHeight, and why it matters

The grid reserves rowExpand.estimatedHeight pixels the moment a row opens, then measures what your panel actually rendered and corrects. A good estimate makes that correction invisible; a bad one makes the rows below jump once. The default is 200, and both examples here set 96, which is close to what their panels really are.

Content whose height is not known until it arrives — images, a lazily-loaded list — will always settle once. That is expected, and a minimum height on your own panel is the usual way to keep the correction small.

expandMode

  • 'multi' (default) — panels accumulate. Opening one does not close another.
  • 'single' — opening one closes the other, accordion style.

canExpand

canExpand: (row) => boolean decides which rows get a toggle at all. A row that answers false renders with no chevron — not a disabled one — and cannot be opened by mouse or keyboard. Everything else about it is unchanged.

Motion

config.animateRows eases the panel in when a row opens; closing is always instant. The same option governs rows revealed under a group or a tree node, so a grid has one motion setting rather than one per feature, and it is skipped entirely for readers who have asked their system for reduced motion.

Putting a whole nested grid in the panel — rowExpand.subGrid, with its own columns, data source and isolated services per parent row — is part of the enterprise package. The template above is the free way to put anything you like in a panel, including your own components.

Row expansion options

PropertyTypeDefaultDescription
config.rowExpandRowExpandConfig<T>—Turns on the expand toggle column. Panels take real vertical space in the scroll area rather than floating over it.
rowExpand.expandMode'multi' | 'single''multi''single' closes the open panel when another row opens — an accordion.
rowExpand.estimatedHeightnumber200Pixels reserved before the panel is measured. The closer to the real height, the smaller the one-time correction.
rowExpand.canExpand(row: T) => booleanevery rowRows that answer false render with no chevron at all — not a disabled one — and cannot be opened by mouse or keyboard.
#gcExpandRowng-template (ExpandContext<T>)—The panel template, projected inside <gridcraft>. $implicit is the parent row, so let-row is enough.
config.animateRowsbooleantrueEases the panel in on open; closing is always instant. Also covers rows revealed under a group or tree node, and is skipped under reduced-motion.