developer guide
Coming from Handsontable
A concept-to-concept map from a Handsontable grid to Lattice Grid, one before-and-after setup, and a straight answer on the one thing that does not carry across.
How your grid maps across
Most of a Handsontable setup has a direct equivalent here, and the names are close enough that the move reads as a rename rather than a rewrite. You keep your data as objects, keep your columns, keep your editors and validators, and keep the hook that saves a change. The table below is the whole map for the common surface.
| In Handsontable | In Lattice Grid |
|---|---|
data (array of objects) |
rows, with rowKey naming the stable id column |
columns and colHeaders |
columns, each with a field and a title |
type: numeric, date, checkbox, dropdown |
type: number, date, boolean, lookup, plus a library of technical types for units, network, time and more |
numericFormat and dateFormat |
format on the column, using the platform number and date formatter |
renderer |
the cell renderer options: pills, dots, bars and in-cell charts, or a function for full control |
afterChange |
the cell:changed event, and edit.commit for a write that persists and rolls back on rejection |
validator |
validation on the column: the edit is refused and the reason shown before it is written |
filters and dropdownMenu |
a per-column filter, including filter: { type: 'set' } for a checkbox list, a condition tree, and a quick filter across the whole grid |
columnSorting and multiColumnSorting |
single and multi-column sort, on by default |
nestedHeaders |
column groups with grouped, movable headers |
| grouping rows by a value | row grouping with subtotals and a pivot, each group a total the grid computes |
manualColumnResize, manualColumnMove, manualRowMove |
column resize, column reorder and row reorder, on by default |
fixedColumnsStart and fixedRowsTop |
pinned columns and pinned rows, set on the column or the layout |
hiddenColumns |
column visibility and a tool panel that shows, hides and reorders columns |
mergeCells |
cell, row and column spanning |
| copy, paste and the fill handle | clipboard interop with Excel and Sheets, cell ranges, and the fill handle |
undoRedo |
undo and redo across the whole grid |
contextMenu |
a built-in context menu you can extend with your own items |
| the CSV export plugin | Excel and CSV export built in, with no plugin and no dependency |
| a formula typed into a cell | a formula that names columns rather than cell addresses, evaluated when it is committed, with computed columns for a value that must stay in step |
Before and after
The same three-column grid, editable and filterable, with a save on every change. First in Handsontable, then in Lattice Grid.
Handsontable
import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.css';
new Handsontable(el, {
data: rows,
colHeaders: ['Circuit', 'Region', 'Monthly charge'],
columns: [
{ data: 'circuit' },
{ data: 'region' },
{ data: 'charge', type: 'numeric', numericFormat: { pattern: '$0,0.00' } },
],
columnSorting: true,
filters: true,
dropdownMenu: true,
afterChange(changes, source) {
if (source === 'edit') save(changes);
},
licenseKey: 'non-commercial-and-evaluation',
});
Lattice Grid
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
const grid = createGrid(el, {
rowKey: 'id',
columns: [
{ field: 'circuit', title: 'Circuit' },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'charge', title: 'Monthly charge', type: 'number',
format: { style: 'currency', currency: 'USD' }, total: 'sum' },
],
rows,
edit: { enabled: true, commit: (change) => save(change) },
});
// The write already happened on screen; commit persists it and rolls back
// on a rejection. The cell:changed event reports every accepted edit.
grid.on('cell:changed', (e) => console.log(e.field, e.value));
The shape is the same: your rows, your columns, an editor, a filter and a
save. Formatting moves onto the column as format, the set
filter replaces the dropdown menu, and the save is an edit that applies on
screen at once and asks your server to confirm, rolling the cell back to
its last confirmed value if the write is refused.
What our formulas do, and where they stop
Check this against your sheet before you plan the move, because it is the one place where a workbook can fail to survive it.
What carries across: a user types = into a cell and gets a real
formula. =quantity * unitPrice,
=ROUND(quantity * unitPrice, 2),
=IF(quantity > 10, "bulk", "single"),
=MAX(readings) - MIN(readings), and functions of your own
registered beside the built-in ones. References name columns rather than cell
addresses, so a formula means the same thing after the grid is sorted,
filtered, grouped or paged, and it is parsed rather than run, so text a user
typed never reaches the JavaScript engine. A formula commits as one undo
step and goes through the column's validation like any other value.
Where it stops: a typed formula is evaluated once, at the moment it is committed, and what lands in the cell is a value. It does not re-evaluate when a cell it referred to changes later. For a value that must stay in step with its inputs, declare a computed column and the grid keeps it current as its dependencies move. So a sheet whose point is a chain of cells recalculating each other is the part to plan for; a column that is those two multiplied moves over as it is.
For pricing, licensing and a live grid to click through, see the Handsontable comparison. To start building, the developer guide and the editing guide cover the rest.