Install and import
Angular's components ship as an entry point inside the same package, at
@toclocoinc/lattice-grid/angular, compiled by @angular/compiler-cli into a
partial-Ivy library your own build links, with no JIT compiler needed in the page and no second
package to keep in step with the grid's own version.
npm install @toclocoinc/lattice-grid
# @angular/core and @angular/common are optional peer dependencies:
# nothing extra installs on a non-Angular project
# free on localhost; a production domain needs a licence key (see /pricing/)
The files
cell-editing.component.ts
// cell-editing.component.ts
import { Component, viewChild } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { LatticeGridComponent, provideLattice } from '@toclocoinc/lattice-grid/angular';
// edit on the grid switches editing on; edit on a column says which columns
// take it. "circuit" carries no edit key below, so it stays read-only even
// though editing is on for the grid as a whole.
const COLUMNS = [
{ field: 'circuit', title: 'Circuit', layout: { width: 180 } },
{ field: 'region', title: 'Region', edit: true },
{ field: 'status', title: 'Status', filter: { type: 'set' }, edit: true },
{ field: 'bandwidth', title: 'Bandwidth', type: 'number', filter: { type: 'number' }, edit: true },
{ field: 'charge', title: 'Monthly charge', type: 'number',
format: { style: 'currency', currency: 'GBP' }, filter: { type: 'number' }, edit: true },
];
@Component({
selector: 'app-cell-editing',
standalone: true,
imports: [LatticeGridComponent],
template:
'<lattice-grid #grid [config]="config" (cell-changed)="onCellChanged($event)" ' +
'style="display:block;height:460px"></lattice-grid>',
})
export class CellEditingComponent {
grid = viewChild<LatticeGridComponent>('grid');
config = {
rowKey: 'id',
selection: 'multiple',
edit: true,
columns: COLUMNS,
rows: [] as unknown[], // circuit records
};
onCellChanged(e: unknown) { console.log('cell changed', e); }
}
bootstrapApplication(CellEditingComponent, {
providers: [provideLattice({ createGrid })],
});
row-editing.component.ts
// row-editing.component.ts
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { LatticeGridComponent, provideLattice } from '@toclocoinc/lattice-grid/angular';
// mode: 'row' opens the whole row for editing at once, as one transaction,
// rather than one cell at a time.
const COLUMNS = [
{ field: 'circuit', title: 'Circuit', layout: { width: 180 } },
{ field: 'region', title: 'Region', edit: true },
{ field: 'status', title: 'Status', filter: { type: 'set' }, edit: true },
{ field: 'bandwidth', title: 'Bandwidth', type: 'number', filter: { type: 'number' }, edit: true },
{ field: 'charge', title: 'Monthly charge', type: 'number',
format: { style: 'currency', currency: 'GBP' }, filter: { type: 'number' }, edit: true },
];
@Component({
selector: 'app-row-editing',
standalone: true,
imports: [LatticeGridComponent],
template: '<lattice-grid [config]="config" style="display:block;height:460px"></lattice-grid>',
})
export class RowEditingComponent {
config = {
rowKey: 'id',
selection: 'multiple',
edit: { enabled: true, mode: 'row' },
columns: COLUMNS,
rows: [] as unknown[], // circuit records
};
}
bootstrapApplication(RowEditingComponent, {
providers: [provideLattice({ createGrid })],
});
See it running
Open this demo's Angular tab →
Open this demo's Angular tab →
Working in Angular
Reaching the grid. A template reference variable (#grid) plus a
signal query (viewChild(LatticeGridComponent)) gets you the component; its own
grid() getter is the live instance, the same object createGrid itself
would return.
Inputs are compared by identity, and never rebuild the instance. A changed
[config] reaches the grid already on screen through setAll; an inline
object literal in the template is a new object on every change-detection pass, so hold
config in a field, as both components do above, not inline in the template.
Events are outputs under their kebab-case name: cell:changed arrives
as (cell-changed), and (grid-ready) hands you the instance the moment it
exists, before any change-detection cycle has to run.
No zone assumptions. The grid is created outside NgZone, because it
owns its own scroll and pointer handling; a bound output still re-enters the zone and repaints as
expected, and this works the same under zoneless change detection.
Related
Read the docs Angular data grid overview Free on localhost. See pricing.