Lattice Grid 1.76: ClickHouse, MotherDuck and the Leaflet map
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),
},
Dropdowns that follow a live source
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.