Lattice Grid Buy a licence

blog

Why we built our own grid

Building…
Loading a live grid…

Nobody sets out to write a data grid. You set out to ship a screen, the screen turns out to need a table with fifty thousand rows in it, and a fortnight later you are reading pointer events documentation at eleven at night because column resizing is subtly wrong in Safari.

So the sensible first move is the one everybody makes: draw a table of what is available and pick something. The grid above is that table, as we actually drew it. Sixteen capabilities down the side, three approaches across the top, and an honest assessment in each cell rather than a tick. Group it by area, filter the approach columns, and read the last column, which is the one that decided it.

Three shapes of problem, none of them features

The first shape is priced per developer. A grid gets installed once and touched by everybody afterwards: the person who built the screen, the contractor covering a sprint, the engineer fixing a bug two years later, the agency doing the redesign. Per-seat pricing turns each of those into a line item and, worse, into a conversation with procurement. We modelled it for a team we expected to double and the number went up faster than the team did, which is a strange thing to be punished for.

The second shape is coupled to a framework. The grid arrives as a component for one library, and from then on that library is load bearing. Not because you chose it, but because migrating away means replacing the busiest screen in the product. A grid that only works in one framework is a grid that has opinions about your next three years.

The third shape is headless. Headless libraries are genuinely good engineering and they solve the half of the problem we did not have. They hand you a sort state, a filter model and a row model, and then you write the header, the drag handle, the resize cursor, the filter menu, the roving focus, the virtualised body and the accessibility. Look at the middle column above and count how many rows say you finish it yourself. That is not a criticism of headless; it is a description of what headless is for.

The row that actually decided it

Scroll to the bottom group and read the last three rows, because those are the ones that are not capabilities at all.

“Your choice of framework” is the row where headless and writing your own both win outright, and a bundled grid usually does not. “Adding a developer without adding a licence” is the row where writing your own wins and everything else costs money. And “someone else fixing it at midnight” is the row where writing your own loses so badly that it usually ends the conversation.

We wanted all three at once, which was not on offer. So we wrote one, in vanilla JavaScript, with no runtime dependencies, and ran it inside our own platform against live customer data for years before it had a price. Adapters for React, Vue and Svelte ship as optional bundles, and none of them is required, because the grid does not know or care which one is loaded.

The caveats are the useful column

The column we would read first if somebody else had published this table is the last one. “CSV is a morning. A spreadsheet where the currency column is still currency is not.” “Getting the total right after a filter is the bug every hand-written grid ships at least once.” “Roving focus over a virtualised body is harder than it sounds, because the cell you are moving to may not exist yet.”

None of those appear in a feature matrix. All of them appear in month four, and month four is when the person who made the decision is still the person answering for it. Every one of those sentences cost us a month to get right, which is why they are in the grid rather than in a footnote.

The table has no column for our own product on purpose. If it did it would be the first column with different pricing, and you would be right to distrust a scorecard written by one of the entrants. Read the three approaches, decide which shape of problem you can live with, and then go and check whether we solved the one you cannot.

Development on localhost is free and needs no key, so the checking costs nothing.

See it running or start with the docs.

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.

  • The table is the schema

    htmx renders the table on the server; Lattice Grid upgrades it into a live grid in place, columns and rows read straight from the markup, and it survives htmx swaps.

  • Swap the import

    A compatibility layer gives Lattice Grid the shape of dhtmlx's dhx.Grid, so the constructor, the data and selection namespaces and the events keep working. Swap the import.

All posts RSS