Lattice Grid Buy a licence

blog

Filter and Map Location Data in a JavaScript Grid

Building…
Loading a live grid…

A table of sites, stores or claims usually keeps a postcode or a pair of numbers for where a row is. Finding “everything inside this box” or “the five closest to here” then means pulling every row into the browser and testing each one by hand, or writing that logic again for the next table. A grid column can hold the shape itself instead: a point, a line or a polygon, filtered, sorted and drawn like any other value.

A column can hold a shape

Declare a column type: 'geometry' and it reads a point, line or polygon from WKT, WKB or GeoJSON, whichever a source hands it, and shows a plain sentence in the cell: a coordinate, or a shape and its area. Four filters come with it, on top of everything every other column already offers: within a box, within a polygon, intersecting another shape, and within a distance of a point. Sort the column and rows order by location.

grid.filters.set({ col: 'site', op: 'withinBbox', value: [-4, 50, 2, 56] });

GeoParquet, read in the browser, filtered by DuckDB

Point the DuckDB adapter at a GeoParquet file with spatial: true and those same four filters run inside DuckDB itself rather than in the browser, over a file that stays where it is. The remote GeoParquet demo puts this against a real 203 MB extract of places data, sorted so that nearby places sit together in the file: filtering a neighbourhood-sized box down fetches around 40 MB of it, not the whole file, and the first rows arrive in about seven seconds while the engine loads. Every filter after that is fast, because the browser never asked for more than the rows in view. The GeoParquet demo on this site shows the same pushdown on a smaller file, with the query plan printed beside the grid so the filter’s own SQL is there to read.

Maps that are viewers, not pictures

markermap, bubblemap and choropleth all read a geometry column directly: a point places a marker, and on a choropleth a polygon draws its own boundary, filled by a measure from the same row, with no separate map file to load and join by code. The choropleth demo fills each country from the shape in its own row. The power plants demo carries close to 35,000 sites worldwide: zoomed in, every plant draws as its own bubble; zoomed out past the cap of 20,000 points in one view, the map switches to density cells instead of thinning the set at random, so the picture stays honest at any scale. The live earthquakes demo draws the same map against a feed that keeps moving.

Pan the map, narrow the grid

Turn on viewportFilter and panning or zooming a map writes one condition back onto the grid it reads from: whatever is on screen becomes the filter, and every other chart, tile or table reading that same grid follows it. Set a matching condition from somewhere else, a saved view or a sibling panel, and the map pans to meet it instead of fighting it. The viewport filter demo puts a map and a grid side by side on one filter, either one able to drive it.

Tiles and charts that ask the engine

A KPI tile or a chart sitting beside a grid that only holds a page of a much larger table used to describe that page, not the true total. Ask a tile to total a filtered column and it reads the whole matching set through the same adapter the grid uses, then says so: chart.provenance() reports whether a figure came from the engine or from the browser, so a number on screen never has to be trusted blind. The engine tiles demo totals a column across a paged DuckDB source this way, in step with the grid’s own filters.

Or draw it yourself, with deck.gl

The built-in maps cover markers, bubbles and choropleths; a page already building its view in deck.gl can bind the grid to it directly instead. bindDeck hands your own deck.gl layers exactly the rows the grid shows, redraws them as the grid changes, and turns the map’s own pan and zoom into the same viewport filter the built-in maps write. The deck.gl demo draws a scatterplot layer over a real basemap this way, straight from the grid’s rows. The GIS demo goes further: a world choropleth of generating capacity by country, a hexagon density layer as you zoom into a region, and the plants themselves at city scale, each layer fed by the same grid and the same filters, with the map’s viewport narrowing the rows as you move.

See it running

The geospatial guide covers the column type, the four operators and every map option in full, and the full changelog lists everything else this release shipped.

Read next

All posts RSS