Lattice Grid Buy a licence

api reference

Lattice Grid API reference

How to construct a grid, the configuration and column specs, and the grid methods. Each namespace has its own page below; the full reference is one archive away.

Version 1.13.0 Zero dependencies Developer guide →

Construction

Two files are all you need: a stylesheet and a script. Nothing is fetched at runtime (no CDN, no font, no icon sprite) however the two files themselves got there.

<!-- Script tag, from your own build. Everything is on one global. -->
<link rel="stylesheet" href="dist/lattice-grid.min.css">
<script src="dist/lattice-grid.min.js"></script>

<script>
  const grid = LatticeGrid.createGrid(document.getElementById('grid'), config);
</script>

Or straight from jsDelivr, no npm install, no bundler, no local copy at all:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.7.1/lattice-grid.min.css">
<script src="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.7.1/lattice-grid.min.js"></script>

<script>
  const grid = LatticeGrid.createGrid(document.getElementById('grid'), config);
</script>

Or as modules, importing the bundle by path: your own build, npm, or jsDelivr:

// With a renderer, in a browser. Any of:
import { createGrid } from './dist/lattice-grid.esm.js';
// import { createGrid } from '@toclocoinc/lattice-grid';
// import { createGrid } from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.7.1/lattice-grid.esm.min.js';
const grid = createGrid(document.getElementById('grid'), config);

// Headless: the same API without a renderer. Data, filters, sort,
// grouping, totals, formatting and export all work; grid.element is
// null and the DOM-only chrome is simply absent.
// Runs in Node, for tests and server-side export.
import { createHeadlessGrid } from '@toclocoinc/lattice-grid';
const grid = createHeadlessGrid(config);

jsDelivr mirrors every version published to npm at cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@<version>/<file>. Pin an exact version for anything shipped: @1.7.1, not @latest, so a release does not change what a page already in production loads. The same convention reaches any module: .../modules/htmx.esm.min.js, .../modules/react.esm.min.js, and so on.

Configuration properties

Every key is settable at runtime through grid.set(key, value). Keys marked dom are read by createGrid and ignored by a headless grid.

Data and structure

PropertyTypeDefaultDescription
columns(Column | ColumnGroup)[], Column definitions. Groups may nest.
columnGroupsColumnGroup[], Header grouping declared separately from the columns.
rowsunknown[], Row objects. Held by reference; not copied.
rowKeystring | (row) => string, Stable row identity. Without it the grid assigns a key per row object and warns: enough for sorting, filtering, selection and copying within a session, but change tracking, streaming dedupe, selection persistence and remote reload all switch off, because new objects are new rows.
sourceSourceConfigmemoryWhere rows come from: memory, paged, remote or stream. See Sources.
treeTreeConfig, { path } or { parentKey }, plus label, orphans. Rows form a hierarchy. See Tree data.
detailDetailConfig, { rows, config, render, isMaster, height, cacheLimit, target }. A master row expands into a nested grid, inline or into an element you supply. See Master-detail.
contextunknown, Arbitrary value passed to every callback, so formatters and renderers need no closures over app state.

Defaults and registries

PropertyTypeDescription
columnDefaultsColumnMerged under every column before its own definition.
columnPresetsRecord<string, Column>Named bundles applied with preset: 'money'.
dataTypesRecord<string, DataType>Custom types. Registered ahead of the built-ins, so a name here overrides one of ours.
sampleSizenumberValues read per undeclared column when inferring its type. Default 100.
targetSize'default' | 'large'Raises every interactive target to a comfortable size for touch, leaving the type alone. Applied automatically on a coarse pointer; 'default' opts out of that.
componentsRecord<string, Ctor>Renderers, editors and filters addressable by name.
pipesRecord<string, fn>Template pipes for cell.template.
totalFnsRecord<string, TotalFn>Custom aggregations, addressable from column.total.
variantsRecord<string, VariantDefinition>Semantic colour tokens for decorations.

Behaviour

PropertyTypeDefaultDescription
selectionSelectionConfig | 'single' | 'multiple' | 'none', Object form adds checkbox (a pinned column of row checkboxes), headerCheckbox (tri-state select-all in its heading), groupSelectsChildren, ranges, fillHandle, fill. See Selection and ranges.
editEditConfig | boolean, { enabled, mode: 'cell' | 'row', start: 'single' | 'double' | 'key', enterMovesDown, undoDepth, commit, confirm, pendingTimeout }. The last three turn on optimistic writes.
paginationPaginationConfig | boolean, Local or remote paging.
quickFilterTextstring, Initial quick-filter term. Equivalent to grid.filters.quick(text).
hostFilter{ active(), passes(row) }, An application-level predicate composed with the grid's own filters.
pivotobject, { enabled, groupTotals, totalsLabel, maxColumns, separator }. groupTotals: 'before' | 'after' adds a column group totalling every value column across all pivot values, at the near or far edge; omitted, it adds none. totalsLabel heads it, defaulting to Total. maxColumns defaults to 500, counts the totals group, and fails with a message rather than locking the browser.
grandTotalRowboolean | 'bottom'falsetrue puts it inline at the end of the rows; 'bottom' pins it above the status bar. Maintained incrementally on a memory source: see Grouping, totals and pivot.
pinnedTopRowsobject[], Rows held above the scrolling body. Rendered through the ordinary column pipeline, but not part of the data: not counted, sorted, filtered, grouped, selectable or exported. See Pinned rows.
pinnedBottomRowsobject[], As pinnedTopRows, held below the body instead. Sits under the grand total when both are shown.
fullWidth{ when, render }, Draw matching rows as one band across every column instead of dividing them into columns, a section banner, a note, a “load more” affordance. when(row) picks them, render(params) fills them. Still ordinary data rows in every other respect. See Full-width rows.
groupFooterbooleanfalseA closing total row per group.
totalFilteredOnlybooleantrueTotals reduce the filtered set. false totals the whole dataset, group totals included. See Grouping, totals and pivot.
totalOnlyChangedColumnsbooleanfalseReduce only the totalled columns an edit actually changed. Off by default, it asserts that each total depends on nothing but its own column. See Grouping, totals and pivot.
showTotalInHeaderbooleantrueUnder grouping or pivot, a totalled column's heading names its reduction on a line above the column name. See Grouping, totals and pivot.
allowUnsafeTemplatesbooleanfalseOff by default. Templates are escaped unless this is explicitly set. When set, an interpolated value may contain presentational markup, but script is still removed from it: <script>, <iframe> and the other executable tags, on* handler attributes, and javascript: URLs. The flag permits markup, not code.
licencestring, Signed licence key. Removes the trial watermark; unlocks nothing, because nothing is locked.

Presentation

PropertyTypeDefaultDescription
messagesobjecten-GBReplaces the grid's own text: labels, menus and screen-reader announcements. A partial catalogue laid over the built-in British English one, so anything you leave out stays in English. Twenty catalogues are bundled: EN_GB, EN_US, FR_FR, FR_CA, IT_IT, ES_ES, PT_BR, DE_DE, NL_NL, SV_SE, DA_DK, NB_NO, FI_FI, PL_PL, CS_CZ, HU_HU, RO_RO, UK_UA, EL_GR, JA_JP and AR. They are exports of the package, not separate files, so importing one does not reduce what is bundled. EN_US is a partial overlay carrying only what differs from British English. AR_SA is an alias for AR: the Arabic catalogue is pan-Arabic, and a region appears in a name only where two variants ship. resolveCatalogue(tag) finds the catalogue for any tag, so resolveCatalogue('es-MX') returns the Spanish one. Every key is listed in MESSAGE_KEYS; auditCatalogue() reports what a catalogue of your own is missing.
localestringruntimeBCP-47. Drives every formatter and one shared Intl.Collator.
direction'ltr' | 'rtl' | 'auto'autoWriting direction. Left unset, it follows the element's computed dir and then the locale, so locale: 'ar' renders right to left without further configuration. Set it explicitly to override both.
theme'light' | 'dark' | 'high-contrast' | 'terminal', Stamped as data-theme on the grid's root. Unset follows the viewer's prefers-color-scheme. See Theming.
density'compact' | 'standard' | 'comfortable' | 'spacious' | number'compact'One scale that every geometry token derives from: row height, spacing, decoration sizes, and type at a damped rate. Row heights are 23.8 / 28 / 42 / 56px. A number scales 28px, so 1.4 gives 39.2px for anything between the presets. Virtualisation follows it; an explicit rowHeight overrides it.
rowHeightnumber | (row) => number28A function enables variable-height rows.
headerHeightnumber32Per header row.
titlestring, A caption drawn above the column headings. Inside the grid rather than an element placed above it, so it scrolls with the grid, sits in the region a screen reader announces, and is kept by image capture and print.
showHeaderbooleantrueDraw the column headings at all. false removes the row, and removes it from the accessibility tree rather than only from view. Distinct from showColumnFunctions, which keeps the headings and drops only their sort, filter and menu controls.
overscannumber4Rows rendered beyond the viewport.
autoHeightboolean | 'visible', Size rows to their content: cells wrap instead of ellipsising, and each row takes the height its tallest cell needs. Only rendered rows are measured either way, the difference is that true stops measuring above 10,000 rows and returns to fixed heights, while 'visible' keeps measuring at any size and accepts a scrollbar that shifts as rows are measured on the way past.
columnVirtualisationAbovenumber30Column count above which columns virtualise too.
stateGridState, Restore a saved view at construction.

Performance

PropertyTypeDefaultDescription
useWorkerbooleantrueCompute column distributions off the main thread. Sorting, filtering and grouping run on the main thread.
workerThresholdnumber50000Row count above which a distribution is sent to the Worker.
workerUrlstring, External worker file, for a CSP that forbids blob:. Settled when the Worker is built; changing it rebuilds one.
sharedMemorybooleanfalsePass columns to the worker in a SharedArrayBuffer instead of copying them, where the page is cross-origin isolated. Retains a shared copy of each column that crosses.

Chrome dom

PropertyTypeDescription
statusBarboolean | { panels }Composable panels along the bottom. Default set: rowCount, selectedCount, aggregation, comments, updates, progress. Each is silent when it has nothing to report.
maximisebooleantruefalse removes the rail button and grid.maximise, for an application with its own full-screen mode.
toolPanelboolean | objectSide dock. panels: columns, filters, views, quick, formatting, statistics. side: 'left' makes it the icon rail, which also turns on actions (undo, redo, pause, restore, maximise, then the export group: export, excel, clipboard, print: nine in all, and an array takes these names rather than the button labels) and icons. An explicit array replaces that list rather than extending it; a bare '-' in it renders a divider between groups. exportName names the CSV.
timeZonestringAn IANA zone every date column formats and parses in, so a grid shows one zone whatever the viewer's machine says. Individual columns may override it.
formulaFunctionsobjectYour own functions, added to the formula language by name. The built-in list is closed on purpose; this is the one way in, and a function you add is called exactly as a built-in is.
formattingobjectConditional formatting rules to seed, keyed by column id or '*'. The same shape grid.formatting.all() returns, so a saved view can be handed straight back.
facetsboolean | objectHeader histograms that double as a filter. collapsed, height, and per-column strategy and buckets.
updatesobjectHow a live feed behaves: batching, the queue that holds while paused, and the highlight a changed cell flashes.
commentsobjectThreaded cell comments: storage, the current author, and whether the indicator shows on an unread thread.
presenceobjectLive cursors, selections and edit locks. Carries intent and never values; see grid.presence.
environmentfunctionExtra fields for the diagnostics bundle: build number, tenant, region. Called when a bundle is taken, never on the render path.
contextMenuboolean | (p) => MenuItem[]Right-click menu. The function form is (params, defaults) => items: see custom items. false suppresses it: what a read-only grid wants, since the default menu offers Paste, Clear and Fill down.
columnMenuboolean | (p) => MenuItem[]The header's 3-dot menu, and a right-click on a column heading. The function form is (params, defaults) => items, with params carrying colId, column and grid: see custom items. false suppresses it.
shortcutsbooleantrueThe ? keyboard shortcut overlay. false suppresses it, for a host that wants ? for itself. See Keyboard.
rowReorderboolean | { column }, Let a user reorder rows by dragging a handle or with Alt+Shift+arrows. The handle goes in the first visible column unless column names another. Refused, with a reason announced, while a sort, filter or grouping is active. See Row reorder.
rowTransferboolean | { send, receive, mode, group }, Let rows be dragged between grids. Off by default. send and receive are both on when present, so one-way is { receive: false } or { send: false }. mode: 'copy' leaves the row behind; group restricts which grids may exchange. See Moving rows between grids.
alignedGridsGrid[], Other grids to stay column-aligned with. Widths, order, visibility, pinning and horizontal scroll are shared; sort, filters, selection and rows stay independent. Declare it on the grid created last. See Aligned grids.
stickyGroupHeadersboolean | number | { depth }trueKeep the enclosing group headings pinned above the viewport while scrolling inside a group. Stacks at most two by default; each costs a row of viewport. See Sticky group headings.
gridLinesboolean | 'both' | 'horizontal' | 'vertical' | 'none''horizontal'Which rules are drawn between cells. Horizontal is what the grid has always drawn; vertical rules are additive. 'rows' and 'columns' are accepted aliases. Only the rules between data are affected, the header underline and pinned seams are structure.
cornerRadiusboolean | number | string, Round the grid's outer corners. true adopts the theme's radius, a number is pixels, a string is used as written.
columnTagFilterboolean | { multiple, label }, A bar above the headings for showing only the columns carrying a chosen tag. Draws nothing unless some column has tags. See Column tags.
rowTemplatestring | { template, cardsPerRow, maxCardWidth, gap, className, role, itemRole }, Draw each row with a template instead of dividing it into columns, a card list, a feed, a search-result list. Compiles once; binds with {{data.field}}. cardsPerRow or maxCardWidth puts several on a line. The pipeline underneath is unchanged. See Cards, lists and feeds.
responsive{ maxWidth, template, rowHeight }, Collapse to cards when the container is at or below maxWidth (640 by default), and return to a table above it. Sorting, filtering and export keep working. Emits presentation:changed. See Cards, lists and feeds.
rowFormboolean | { mode, load, fields, title, width, trigger, timeout, container }, Open a row for editing on a form. mode: 'drawer' (default) or 'dialog'; without load the fields are the grid's own columns. A field entry is { field, label, editor, type, props, lookup }: any editor, including your own. Takes double-click on the row unless trigger: false. A load that has not answered within timeout milliseconds (2000; false waits indefinitely) is reported as a failure with a retry. container builds the form in an element of your own instead of over the grid. See Editing a row on a form.
showColumnFunctionsbooleantruefalse leaves each heading as its label, with no sort, filter or menu control. Those remain reachable through the API, the keyboard and the tool panel.
significantFiguresnumber, On a unit column, render to this many significant figures rather than a fixed number of decimals, so precision is the same on every rung of the ladder. Rounding is applied before the unit is chosen. Set inside the unit configuration a data type is built from. See Units.
typeOptionsobject, Per-column options a data type reads. ratio and percentRate use { weight } to name the column their average is weighted by. See Aggregate safety.
highlightOnChangeboolean | string | objectFlash a cell when its value changes. { colour, duration }; duration: 0 stays until cleared.
rowClassstring | string[] | (p) => …A class, or classes, for every row. Re-evaluated on each repaint.
rowStyleCellStyle | (p) => CellStyleInline styles for every row. Camel-case or hyphenated property names.
viewsobjectsaved, allowSave, storage. See grid.views.
permissionsstring | object | fnPer-column access. See grid.permissions.
diffobject{ snapshot } turns on audit mode.
historyBarboolean | objectA standalone undo/redo toolbar with a timeline.
aiobject{ ask } mounts the prompt bar. Your ask receives { prompt, schema, schemaText, message, context } and returns the model's reply.
dataTypesobjectCustom types by name. createRadixType and createUnitType are exported for building them.
editBarbooleanA spreadsheet-style input above the header. When on, it hosts the column's real editor and inline editing is suppressed.
paginationboolean | objectRenders the pager control: page size, a summary, first/previous/next/last, and a page number you can type into and press Enter to jump.

Column definition

Everything is optional. A column with only field infers its type from sampled data and takes every default from there.

PropertyTypeDescription
idstringDefaults to field. Required when there is no field.
fieldstringDotted paths supported: 'site.address.postcode'.
titlestringHeader text. Defaults to a humanised field.
typeTypeName | falseA data type bundles format, parse, compare, storage, editor, filter, renderer and Excel behaviour. false disables inference. 'image' treats the value as a URL and draws it: see image columns.
presetstring | string[]Named bundles from columnPresets.
tagsstring | string[], Labels grouping columns together, used by the column tag bar. A bare string is accepted for one tag.
formatFormatSpec | stringShorthand strings like 'percent:1' or 'date:dd MMM yyyy'.
lookupLookupSpecId-to-label mapping. Nested children are flattened, so a tree-shaped list resolves labels everywhere.
valueColumnValueSpecComputed values and the value lifecycle.
cellColumnCellSpec | stringA bare string is a renderer name.
editColumnEditSpec | boolean | stringA bare string is an editor name.
sortColumnSortSpec | boolean
filterColumnFilterSpec | boolean | FilterName
groupobject | boolean{ enabled, index, explode }.
pivotobject | boolean{ enabled, index }.
totalTotalName | TotalFnOne property drives the group row, the tree node, the pivot cell and the grand total.
layoutColumnLayoutSpec | numberA bare number is the width.
headerColumnHeaderSpec | string
exportColumnExportSpec{ lookup: 'label' | 'value' | 'columns', csv, excel }.
allowGroup / allowPivot / allowTotalbooleanWhether the tool panel offers the column for that zone.
nullablebooleanAffects storage choice and null ordering.

Column sub-specs

value

KeyTypeDescription
compute(deps, ctx) => unknownDerived value. Receives only its declared dependencies.
depsstring[] | '*'Declared dependencies. Cycles are caught at compile time, not at render.
purebooleanAllows caching. A DEV-mode proxy flags impure computes that read outside their deps.
format(p) => stringOverrides the type's formatter.
parse(p) => unknownEditor output to value. Always called, whatever the editor emitted.
apply(p) => booleanWrites the value back into the row object.
key(p) => stringGroup key override.
compareComparatorOverrides the type's comparator.
quickFilterText(p) => stringWhat the quick filter matches against.

cell

KeyTypeDescription
renderRendererName | RenderFn | CtorRenderer name or component. The built-in names are listed under built-in renderers.
propsobjectPassed to the renderer.
decorationDecorationName | specpill, bar, fill, dot, edge.
variantVariantSpecMaps a value to a semantic token: { map }, or { when: [...], default }.
templatestringEscaped unless allowUnsafeTemplates is set.
classstring | string[] | (p) => …Classes for this column's cells.
classWhen{ [class]: (p) => boolean }A class per predicate, re-evaluated as values change.
style / cssCellStyle | (p) => CellStyleInline styles, static or computed.
tooltipstring | (p) => string
align / wrap / autoHeight, Presentation flags.
spanColumns / spanRows(p) => numberSpanned cells render in their own layer so row recycling cannot clip them.

Custom CSS, by scope. Cells: cell.class, cell.classWhen, cell.style and cell.css, all of which may be functions of the cell. Columns: the same four, declared on the column, so they apply to every cell in it; the header takes header.class. Rows: rowClass and rowStyle on the grid.

All of them are re-evaluated on every repaint and remove what they added last time first. That is not caution: rows and cells come from pools, so an element that carried a class for one row will later carry a different row, and a class written once and left alone smears down the grid as the user scrolls.

edit, sort, filter, layout, header

SpecKeys
editenabled (boolean or predicate), editor, props, popup, validate
sortenabled, direction, order, nullsFirst
filterenabled, type, props
layoutwidth, min, max, flex, pin, hidden, resizable, movable, lockVisible, lockPosition. A pin of 'start' or 'end' holds the viewport edge while there is something to scroll; where the columns do not fill the grid, spare width falls beyond the last column rather than in front of it.
headertemplate, render, props, class, tooltip, align

Grid methods

Top-level members. Everything else hangs off a namespace.

MemberReturnsDescription
getVersion()stringThe version this grid came from, e.g. '1.7.1'. Also on the module as getVersion(), for when you have no grid to hand.
get(key)unknownRead any configuration key.
set(key, value)voidWrite one key. Every key is live; nothing needs a rebuild.
setAll(values)voidWrite several in one pass. Emits one config:changed for the batch, not one per key.
config()GridConfigThe whole live configuration as a shallow copy. Pairs with setAll for a read-modify-write round trip. Nested objects are shared by reference, so treat it as read-only.
setPinnedRows(rows, opts?)voidPin rows outside the scrolling body. opts.edge is 'top' (the default) or 'bottom'. Pass a new array rather than mutating the previous one: array identity is the change signal. See Pinned rows.
getPinnedRows(opts?)object[]The objects pinned at one edge, as a copy.
on(event, handler)() => voidReturns its own unsubscribe. '*' subscribes to everything.
once(event, handler)() => void
off(event, handler)void
emit(event, payload)voidEmit on the grid's bus, for custom components.
attachRenderer(renderer)voidBind a renderer to a headless grid.
destroy()voidRelease listeners, workers and pooled buffers.
elementHTMLElement | nullThe rendered root; null when headless.
readyboolean
destroyedboolean

The reference, by namespace

Each area of the API is its own page, so you can link to the one that documents the method in front of you.