developer guide
Web Components: JavaScript Data Grid Guide
One script, a tag per view, no build step. For Rails, Django, Laravel or any page without a bundler.
One script, one tag
The web component is a self-contained module that registers a custom element when it loads. Add
the stylesheet and the module, then write the tag. Scalar settings go on as attributes;
columns and rows can be JSON attributes for a small static grid. See its
size and every other module in the module map.
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.103.2/lattice-grid.min.css">
<script type="module" src="https://cdn.latticegrid.dev/lattice-grid@1.103.2/modules/webcomponent.esm.min.js"></script>
<lattice-grid
row-key="id"
columns='[{"field":"circuit","title":"Circuit"},{"field":"charge","title":"Charge","type":"number"}]'
rows='[{"id":1,"circuit":"ETH-LON-1","charge":465.32}]'
></lattice-grid>
A tag for every view
The grid is not the only view with a tag. Alongside <lattice-grid> the same
bundle can register <lattice-kpi>, <lattice-chart>,
<lattice-kanban>, <lattice-gantt>,
<lattice-layout>, <lattice-tabs> and
<lattice-router>, so a whole dashboard is markup on a page with no build
step. You register the ones you use with the factories your page imported, which is what keeps
a page that draws no charts from downloading any chart code.
<script type="module">
import { createKPI } from 'https://cdn.latticegrid.dev/lattice-grid@1.103.2/modules/kpi.esm.min.js';
import { createChart } from 'https://cdn.latticegrid.dev/lattice-grid@1.103.2/modules/charts.esm.min.js';
import { defineLatticeElements } from 'https://cdn.latticegrid.dev/lattice-grid@1.103.2/modules/webcomponent.esm.min.js';
// Register the ones this page uses. Nothing else is downloaded.
defineLatticeElements({ createKPI, createChart });
</script>
<lattice-grid name="circuits" row-key="id"></lattice-grid>
<lattice-kpi grid-name="circuits"></lattice-kpi>
<lattice-chart grid-name="circuits" type="bar" x="region" y="charge"></lattice-chart>
A view finds its grid by name, so a tile strip written above its grid in the markup still
fills the moment the grid arrives and nothing depends on the order the tags appear in. A tab's
content is a <template> child, so a tab can hold a genuine
<lattice-grid> with its own attributes, and
<lattice-router> groups one live feed across every view inside it. Changes
go into the view that is already on screen rather than a new one: replace the rows fifty
times, or move the element somewhere else in the page, and your scroll position, selection and
expansion are still there. Events arrive as CustomEvents under a
lattice- name, and type declarations cover every element.
Inside a shadow root of your own
A stylesheet does not cross a shadow boundary, so a view placed inside a component that
attaches its own shadow root would render perfectly and completely unstyled. Every Lattice
element now mirrors the theme, each module's stylesheet and the grid's own into its root and
keeps them level as the grid compiles new classes, so a view inside a Lit or Stencil
component, a micro-frontend container, or Angular with shadow DOM encapsulation, is styled
like every other. Call adoptLatticeStyles(root) for a root you own,
latticeStyleSheets() if you manage adopted stylesheets yourself, or
lattice-styles="off" to opt an element out.
Attributes for scalars, properties for data
A JSON attribute is fine for a handful of rows, but real data goes on as a property, which
carries a live value rather than a string the element has to parse. The grid instance is on
.grid once the element has upgraded, so the whole public API is one property away.
const el = document.querySelector('lattice-grid');
// Structured values go on as properties, not attributes.
el.columns = columns;
el.rows = rows;
// The real grid instance is on .grid once the element has upgraded.
el.grid.export.csv({ download: true });
It carries the grid inside it
Use the custom elements or createGrid, never both on one page. The
web component bundle carries its own copy of the grid, so loading it beside the main build, or
beside a framework adapter, puts two grids in one document. Two copies keep separate registries:
a renderer, type or theme registered through one is invisible to the other, and the failure is
the kind that looks like a bug in your code. Pick one entry point per page and stay on it.
When to reach for it
Reach for these elements on a page that has no bundler, a server-rendered template from Rails,
Django or Laravel, a CMS block, a plain HTML file, where an import is not
available and a script tag is. On a page that already bundles, the base build or a
framework adapter is lighter, because it does not ship a second copy of
the grid.
See the web component demo and the developer guide.