demo D28
Lookups in Angular
Store an id, show a label, sort on the label and edit by picking one
lookup: { options }
This grid stores a compact code in each row but shows a readable label, sorts by that label, and lets a user edit by picking one. It is the pattern behind status fields and any foreign key, so the data stays clean while the display stays legible.
This is the Angular version. A standalone component takes the whole configuration through one config input, surfaces grid events as outputs, and exposes the live grid on a getter for anything the inputs do not cover.
The configuration
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';
// Each row stores a site id; the lookup shows its label instead, and sorts,
// filters and groups by that label.
const SITES = [/* { id, label, group? } per site */];
const columns = [
{ field: 'hostname', title: 'Hostname', layout: { width: 280, pin: 'start' } },
// The same field with no lookup, so the integer the row actually holds is
// visible beside the label it is shown as.
{ field: 'site', id: 'stored', title: 'Stored', type: 'number', layout: { width: 110 } },
// Sorting is on the label by default, which is what someone reading the
// column expects. sortBy: 'value' puts it back on the id.
{ field: 'site', title: 'Site', type: 'lookup', layout: { width: 200 },
lookup: { options: SITES, unknownLabel: 'decommissioned', sortBy: 'label' } },
{ field: 'site', id: 'byValue', title: 'Site, sorted by id', type: 'lookup', layout: { width: 200 },
lookup: { options: SITES, unknownLabel: 'decommissioned', sortBy: 'value' } },
// group on an option is what the select and the set filter use to section a
// long list.
{ field: 'site', id: 'grouped', title: 'Site, grouped options', type: 'lookup', layout: { width: 200 },
lookup: { options: SITES, unknownLabel: 'decommissioned', groupKey: 'group' } },
{ field: 'managed', title: 'Managed', type: 'boolean', layout: { width: 120 } },
{ field: 'ports', title: 'Ports', type: 'number', layout: { width: 110 } },
{ field: 'commissioned', title: 'Commissioned', type: 'dateString', layout: { width: 160 } },
];
const rows = [/* nodes, each holding a site id */];
@Component({
selector: 'app-root',
standalone: true,
imports: [LatticeGridComponent],
template: '<lattice-grid [config]="grid" style="display:block;height:540px"></lattice-grid>',
})
export class AppComponent {
grid = {
rowKey: 'id',
toolPanel: { side: 'left', panels: ['columns', 'filters', 'views', 'quick'],
actions: ['undo', 'redo', 'export', 'restore', 'maximise'], exportName: 'lattice-demo' },
columns: columns,
state: { sort: [{ col: 'site', dir: 'asc' }] },
rows: rows,
};
}
bootstrapApplication(AppComponent, {
providers: [provideLattice({ createGrid })],
});
Mapping stored codes to display labels with lookup columns
A lookup column stores a compact code in each row but shows a reader something legible, and sorts by that label rather than the underlying code. This is the pattern behind status fields, currency codes and any foreign key drawn from a small fixed list, where the raw value on the row is an id such as 2 or "ACT" and the value a reader needs is “Active” or “Pending review”. Lattice Grid handles this with lookup: { options } on the column definition: options supplies the code-to-label pairs once, at column setup, and every cell resolves against that same map rather than repeating the label in the row data. Sorting and filtering operate on the resolved label by default, so a status column orders “Active” before “Pending” as a reader expects, not by the numeric order of the codes.
A developer reaches for lookup instead of a plain text column whenever the stored value and the displayed value diverge, keeping row data small while the grid does the translation at render time. The map builds once from options rather than being looked up per cell, so resolving a label costs a single property read, and a lookup column in a large JavaScript data grid carries no more per-row overhead than a plain text cell.
A lookup column edits the same way it reads. Add edit: { enabled: true, editor: 'select' } and the cell opens a picker over the same options: a reader chooses the label they see, and the grid writes back the underlying id, so the stored value stays compact while the person editing never has to know the code behind it.
How do you show a label for a coded value in a JavaScript data grid?
Set type: 'lookup' on the column and pass lookup: { options }, where options maps each stored code to its display label. Lattice Grid renders the label in the cell and sorts by the label rather than the code, so a status or category column reads naturally without changing what is stored in the row.