Tree data

Nest rows into an expandable hierarchy with the treeData prop.

Open the live example: Tree data (hierarchy) (Sorting & Grouping)

Tree data in SvGrid (33 s, silent).
Transcript

Tree data is one prop. Point treeData at the parent field and name the tree column, and flat rows become a hierarchy.

Click an expander to open a branch. Children indent under their parent and keep every column.

Expand all and Collapse all walk the whole tree through the grid API.

Nested objects work too: flatten them once with flattenTreeData, and the same prop takes it from there.

Tree rows are real data rows. They keep their own cells, formatting, editing and selection, and only gain an expander plus indentation in the tree column. That is the difference from row grouping, where the parent is a synthetic full-width banner standing in for its children.

Flat data (parent id)

The model nests by parent id, so data that already carries one needs no preparation:

The examples on this page run against these rows:

<script lang="ts">
  import { SvGrid, type GridColumns } from '@svgrid/grid'

  type Person = {
    id: number
    name: string
    email: string
    department: string
    age: number
    salary: number
    city: string
    startDate: string
    active: boolean
  }

  const people: Person[] = [
    { id: 1, name: 'Ada Lovelace',   email: '[email protected]',   department: 'Engineering', age: 36, salary: 142000, city: 'London',   startDate: '2021-03-01', active: true },
    { id: 2, name: 'Grace Hopper',   email: '[email protected]', department: 'Engineering', age: 45, salary: 168000, city: 'New York', startDate: '2019-07-15', active: true },
    { id: 3, name: 'Linus Torvalds', email: '[email protected]', department: 'Platform',    age: 54, salary: 155000, city: 'Portland', startDate: '2020-01-20', active: false },
    { id: 4, name: 'Radia Perlman',  email: '[email protected]', department: 'Networking',  age: 49, salary: 161000, city: 'Seattle',  startDate: '2022-09-05', active: true },
    { id: 5, name: 'Barbara Liskov', email: '[email protected]', department: 'Platform',  age: 52, salary: 172000, city: 'Boston',   startDate: '2018-11-11', active: true },
  ]

  const columns: GridColumns<Person> = [
    { field: 'name',       header: 'Name',       width: 200 },
    { field: 'department', header: 'Department', width: 150 },
    { field: 'city',       header: 'City',       width: 140 },
    { field: 'age',        header: 'Age',        width: 90 },
    { field: 'salary',     header: 'Salary',     width: 130, format: { type: 'currency', currency: 'USD' } },
  ]
</script>
<script lang="ts">
  import { SvGrid } from '@svgrid/grid'

  const people = [
    { id: 1, managerId: null, name: 'Ada',   title: 'CEO' },
    { id: 2, managerId: 1,    name: 'Grace', title: 'VP Engineering' },
    { id: 3, managerId: 2,    name: 'Alan',  title: 'Principal Engineer' },
  ]
</script>

<SvGrid
  data={people}
  {columns}
  treeData={{ parentField: 'managerId', column: 'name' }}
/>
Option Meaning
parentField Field holding each row's parent id. Required.
idField Field holding the row's own id. Defaults to 'id'.
column Column that carries the expander + indent. Defaults to the first visible column.
indentPx Indent per depth level, in px. Default 12.

Nested data (children arrays)

The grid only builds rows for the objects in data, so children nested inside a parent are never rows. Flatten them first:

<script lang="ts">
  import { SvGrid, flattenTreeData } from '@svgrid/grid'

  const tree = [
    { id: 1, name: 'src', children: [
      { id: 2, name: 'components', children: [{ id: 3, name: 'Grid.svelte' }] },
    ] },
  ]

  // Stamps `__parentId` on every child and returns one flat list, children
  // directly after their parent.
  const rows = flattenTreeData(tree, { childrenField: 'children' })
</script>

<SvGrid data={rows} {columns} treeData={{ parentField: '__parentId', column: 'name' }} />

flattenTreeData takes childrenField, plus optional idField (default 'id') and parentField (default '__parentId') if you want a different link field.

Accessibility

Turning on treeData puts the grid in the treegrid role. Every row gets aria-level, and expandable rows get aria-expanded. Keyboard:

Key Action
Expand the focused row
Collapse the focused row
Enter / click Toggle via the expander button

Rows without children render a spacer where the chevron would be, so values stay aligned with their expandable siblings.

Edge cases

Server-side trees

For hierarchies too large to send at once, load children on demand with serverGroup and ServerDataSource instead - see Server-side data. The two share the same treegrid keyboard and ARIA contract.

More examples

Project WBS tree

Phase → task → subtask with % complete that rolls up via effort-weighted average when you edit any leaf.

Open the live example: Project WBS tree (Tree & Hierarchy)

Bill of Materials

Bicycle BOM, 4 levels deep. Edit any leaf part's qty or unit cost; subtotals roll up through the assembly chain to the grand total.

Open the live example: Bill of Materials (Tree & Hierarchy)

See also

Live examples

  • Tree data (hierarchy) - treeData nests rows by parent id into an expandable hierarchy. Tree rows stay real data rows - own cells, formatting, editing - and just gain an expander plus indent. Takes flat parent-id data directly, or nested children arrays via flattenTreeData. Full treegrid a11y with arrow-key expand.
  • Project WBS tree - Phase → task → subtask with % complete that rolls up via effort-weighted average when you edit any leaf.
  • Bill of Materials - Bicycle BOM, 4 levels deep. Edit any leaf part's qty or unit cost; subtotals roll up through the assembly chain to the grand total.

Related articles