Lattice Grid Buy a licence

angular data grid · editing

Angular Grid: Editing

Type into a cell, or edit a whole row as one transaction: both run through the same standalone lattice-grid component, compiled ahead of time by your own build rather than assembled in the page.

Also in: React Vue Svelte

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

Building…
Loading a live grid…

Open this demo's Angular tab →

Building…
Loading a live grid…

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