Lattice Grid Buy a licence

blog

Lattice Grid 1.76: ClickHouse, MotherDuck and the Leaflet map

Building…
Loading a live grid…

A grid spends most of its life reading someone else’s data and writing back into someone else’s system, so this release is mostly about the join between the two: a form that creates a row instead of only editing one, a dropdown that keeps its choices in step with a live feed, and two databases joining the list of sources a grid can read directly. Annotating a chart also gets easier to undo.

The row form can add a row

grid.form.openNew() opens the built-in row form over a blank record instead of an existing one. Fill it in, choose Save, and rowForm.create persists it; the grid adds the row where it belongs, selects it and scrolls to it. A create that the server refuses leaves the form open with what you typed and a reason, exactly the way a rejected edit already does.

rowForm: {
  fields: [{ field: 'name' }, { field: 'category' }, { field: 'price' }],
  create: (values) => api('POST', '/products', values),
},

A lookup column’s options no longer have to be fixed at load time. grid.columns.refreshLookup(colId) re-runs the options function on demand, and a lookup can bind straight to a data router route so its choices update themselves as the underlying feed changes, one refresh per batch rather than one per row. An open editor picks up the refreshed list without being reopened.

ClickHouse and MotherDuck, first-class sources

clickhouseAdapter speaks ClickHouse’s own HTTP interface: point it at a table or a query and filtering, sorting, paging, counting and a grouped average, sum, minimum, maximum or exact distinct count all run inside ClickHouse, with every filter value sent as a typed parameter rather than built into the SQL text. The ClickHouse demo on this site runs live against ClickHouse’s own public playground, read-only and keyless, with the generated SQL on screen beside the grid.

MotherDuck joins the same duckdbAdapter a grid already reads DuckDB through: attach a MotherDuck database with your own token and the adapter reads and writes it exactly as it does a local one. The DuckDB guide covers both.

Leaflet joins deck.gl

bindLeaflet makes a Leaflet layer one more viewer of a grid, the way bindDeck already does for deck.gl: hand it a layers function written with your own copy of Leaflet, and it redraws whenever the grid’s rows or selection change. Turn on the viewport filter and panning or zooming the map narrows the grid to whatever is on screen; a click on a feature selects its row. Neither the grid nor the binding imports Leaflet itself. See it running in the Leaflet demo repository.

A cleaner annotation rail

An eraser tool sits alongside pen, arrow, rectangle and highlight: choose it and a click removes the mark under the pointer, or tab to one with the keyboard and press Delete. A Clear all button removes every mark after a Keep/Clear confirmation, and annotate.remove(id) deletes one mark from code. annotate.add() now answers { id, count } rather than a bare number, so a mark can be found again by id; ordinary arithmetic against the return value still works unchanged.

See it running

The ClickHouse demo and the Leaflet demo repository are both live. The full list of what changed is in the changelog.

Read next

All posts RSS