Lattice Grid Buy a licence

blog

Hierarchies that survive real data

Building…
Loading a live grid…

The hierarchy demo you have seen is always built from a clean nested array, usually written by hand, usually four regions and twelve cities. Your data does not arrive like that. It arrives as a join, or as documents out of a store, and what each row carries is the key of its parent. That is the shape you have, so that is the shape a grid should take:

tree: { parentKey: 'parentId', label: 'name', title: 'Estate' }

Two fields and you have a tree. If your rows instead carry their own ancestry, which is what a materialised path or a breadcrumb column gives you, swap the first field for path: (row) => row.hierarchy and everything below is the same. Levels that no row occupies are synthesised, so a set of rows that names ['Networks', 'Transport', 'Subsea'] with nothing in between still draws Transport as a branch.

The three cases that break the demo

The grid above is a company estate assembled the way estates actually get assembled: a site extract joined to a billing extract, with the two systems disagreeing. Three faults are in there on purpose, and none of them is theoretical.

A row whose parent is missing. Four assets name a site that was decommissioned and dropped from the site extract, while billing kept charging for them. Set orphans: 'Parent not in extract' and they go to a named bucket at the root rather than vanishing. Leave the option off and they are placed at the root instead. Either way they are still rows: they still filter, still sort, and still count towards the total at the bottom, which is the part that matters when the total is money and somebody is about to sign it.

A cycle. Three sites in this data name each other in a ring, so none of the three has a root. There is a fourth, shorter one: a row whose parent key is its own key, which is exactly what a merge that defaults a missing parent to the row’s own id writes. Rows in a cycle are shown at the root, and this is worth knowing precisely because it is not where the orphans go. The two faults look alike and land in different places. Loading this grid writes one console line, naming how many rows were caught in a cycle, rather than a line per row, so an extract full of rings does not bury everything else in the console.

A branch you do not have yet. The Archive division in the grid ships with no children at all, only a count. Give the tree a hasChildren so the node knows to draw an expander, and a loadChildren(row, signal) that returns a promise, and the branch is fetched when somebody opens it. The signal is real: close the branch before the fetch lands and the request is aborted, and the node stays openable rather than being left permanently empty. Rows that arrive this way join the data set like any others, so they sort, filter and export.

Count the rows in the bar above the grid. Nothing was dropped to make any of that work.

Where the tree stops and grouping starts

Two things, because finding them out in week three is worse than reading them now.

Tree nodes are your rows, so the grid shows the values you gave them rather than overwriting them with a computed sum. Where you want rollups over a hierarchy, group instead.

A node’s count is of the rows belonging directly to it, not of everything beneath it, so a synthesised branch and the orphan bucket both count 0.

Everything else here is one config object, and no part of it asked you to reshape your data first. The awkward rows in your extract are the reason the feature is written this way: a hierarchy that only works on hierarchies is a demo, not a component.

See the estate, the orphans and the cycles running or start with the two-field version.

Read next

  • The column knows it holds metres

    In most grids a unit is a formatter, and a formatter is a lie that shows the moment someone sorts. Lattice Grid makes a quantity a data type, so the column stays a number.

  • When the grid became the interface

    Grids are sold to developers, so they are built for developers. Why Lattice Grid ships redaction, annotation and presentation tools to every user as standard.

  • Two ways to show a row's detail

    A row that expands into a nested grid, or a pane beside the list where nothing moves. They solve different problems, and one config field switches between them.

All posts RSS