Lattice Grid Buy a licence

developer guide

Grid API compatibility: JavaScript Data Grid Guide

A compatibility wrapper shaped like the grid API an existing application already calls, so the constructor and the data, selection, history, export and event namespaces keep working after an import swap.

Developer guide › Grid API compatibility

Coming from an existing grid API

lattice-grid/modules/dhtmlx-compat exposes a Grid class shaped like a common grid widget API, the same constructor call, the same .data, .selection, .history, .export and .events namespaces: sitting on top of a real Lattice grid underneath. Swap the import and, for the surface below, the calling code does not change.

The wrapper shares the core the page already loads rather than carrying its own, so load @toclocoinc/lattice-grid alongside it: a bundler wires the shared import automatically (it dedupes against the core your app already imports), and a plain <script src> page loads the global build first. The pay-off is that a licence set on that one core applies to these grids too, and the module is a few kilobytes of translation rather than a second copy of the grid.

A drop-in constructor

import { Grid } from '@toclocoinc/lattice-grid/modules/dhtmlx-compat';

const grid = new Grid(container, {
  columns: [
    { id: 'name', header: [{ text: 'Name' }], width: 200, sortable: true },
    { id: 'qty', header: [{ text: 'Qty' }], type: 'number', editable: true, editorType: 'input' },
  ],
  data: rows,
});

grid.events.on('cellClick', (row, column, event) => {
  // row and column carry .id, row's own fields sit alongside it,
  // the same shape the source API's own IRow/ICol declare.
});

What is covered: column definitions (header, width, sortable, resizable, hidden, editorType, editorConfig, options, template, summary); .data's add/update/remove/ removeAll/parse/load/find/ findAll/exists/getItem/getId/ getIndex/getLength/forEach/serialize/ sort/filter/resetFilter; .selection's setCell/getCell/getCells/isSelectedCell/ removeCell; .history's undo/redo/ canUndo/canRedo/clear/getHistory; .export.csv/.xlsx; and the events cellClick, cellDblClick, cellRightClick, afterEditStart, afterEditEnd, afterSort, filterChange, afterColumnDrop, resize, afterResizeEnd, afterColumnHide, afterColumnShow, afterExpand, afterCollapse, afterSelect, afterUnSelect, afterCopy, afterRowDrop and scroll. Grid-level dragItem: 'row' becomes rowReorder: true: same-grid drag-to-reorder.

cellClick, cellDblClick, cellRightClick, afterEditStart, afterEditEnd and afterSort call your handler with the source API's own positional arguments: (row, column, event), not Lattice's own event object, because that is the source API's own documented signature for them. afterRowDrop calls your handler with (data, event), firing from either a same-grid reorder settling or a row landing here from another grid, the source API has one event name for what Lattice models as two. Every other mapped event calls your handler with Lattice's own event object, under Lattice's own field names, since a wrong guess at a fabricated positional shape is worse than an honest one.

Index means current display order: after sort, filter and grouping: everywhere .data takes or returns one. the source API is not fully consistent about this across its own methods; this is the one meaning, held everywhere.

Cross-grid dragging needs an explicit rowTransfer. the source API lets any two grids with dragItem: 'row' on the same page exchange rows by default; Lattice's rowTransfer is deliberately opt-in per pair, with no source-API property to derive it from, so a caller wanting that behaviour passes rowTransfer straight through as a bonus config key.

What is not. Every before*/can*/cancel* event is unmapped: the source API's convention lets a handler return false to cancel the action, and Lattice has no cancelable-event model to honour that with: approximating one would silently ignore a return false a caller depends on. Row and column drag-negotiation events (beforeRowDrag, dragRowOut, canRowDrop, cancelRowDrop, beforeRowDrop and their column equivalents) are unmapped for the same reason: each can refuse or steer a drag mid-gesture, which Lattice has no live protocol to offer. export.pdf() and export.png() throw: there is no raster export to translate to. .rangeSelection is offered on a best-effort basis and its range shape is this wrapper's own design, not the source API's, a genuine RangeSelection module is a separate part of the source API's own product, and this wrapper does not know its exact shape. The classic pre-Suite-5 object model (string-configured, index-addressed) is a different product in every respect that matters here and is not covered at all.

Calling an unmapped event name does not fail silently: the first subscription logs which name has no Lattice equivalent, so a caller relying on it finds out in development rather than in production.