Lattice Grid Buy a licence

demo D218

The form, four ways

The same row form as a drawer, a dialog, an inline region and a curated set

rowForm: { mode: 'drawer' · 'dialog', container }

Building…
Loading a live grid…

The configuration

import * as ng from '@angular/core';
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import createLatticeGrid from '@toclocoinc/lattice-grid/modules/angular';

const { LatticeGridComponent } = createLatticeGrid({ ng, createGrid });

const fields = [
  { field: 'service', label: 'Service' },
  { field: 'team', label: 'Team' },
  { field: 'region', label: 'Region' },
  { field: 'tier', label: 'Tier' },
  { field: 'instances', label: 'Instances' },
  { field: 'monthlyCost', label: 'Monthly cost' },
  { field: 'notes', label: 'Notes', editor: 'textarea' },
];

// The same form, placed four ways. Only the rowForm option differs:
//   drawer  - a right-hand panel (the default)
//   dialog  - a centred modal
//   inline  - built into an element of your own; a region, not a modal
//   curated - the drawer with a chosen few fields
const modes: any = {
  drawer:  { mode: 'drawer', title: 'Edit service', fields },
  dialog:  { mode: 'dialog', title: 'Edit service', fields },
  inline:  { fields, container: '#inline-form' },
  curated: { mode: 'drawer', title: 'Quick edit',
    fields: [{ field: 'tier', label: 'Tier' }, { field: 'instances', label: 'Instances' },
             { field: 'notes', label: 'Notes', editor: 'textarea' }] },
};

const columns = [
  { field: 'service', title: 'Service', layout: { pin: 'start', width: 150 } },
  { field: 'team', title: 'Team', filter: { type: 'set' } },
  { field: 'region', title: 'Region', filter: { type: 'set' } },
  { field: 'tier', title: 'Tier' },
  { field: 'instances', title: 'Instances', type: 'number' },
  { field: 'monthlyCost', title: 'Monthly cost', type: 'number', format: { style: 'currency', currency: 'USD' } },
];

const rows: any[] = [/* service records */];

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, LatticeGridComponent],
  template:
    '<div style="display:flex;gap:8px;margin-bottom:12px">' +
    '  <button *ngFor="let name of modeNames" (click)="setMode(name)" [attr.aria-pressed]="name === mode">{{ name }}</button>' +
    '</div>' +
    '<div style="display:flex;gap:14px">' +
    '  <lattice-grid [config]="grid" style="flex:1;height:520px"></lattice-grid>' +
    '  <div id="inline-form" style="width:320px"></div>' +
    '</div>',
})
export class AppComponent implements AfterViewInit {
  @ViewChild(LatticeGridComponent) gridRef!: LatticeGridComponent;
  modeNames = Object.keys(modes);
  mode = 'drawer';

  grid: any = { rowKey: 'id', editable: true, rowForm: modes['drawer'], columns, rows };

  // The rowForm option carries the whole configuration, so changing it
  // reconfigures in place. Open the first row after each switch, so the
  // placement shows.
  setMode(name: string) {
    this.mode = name;
    this.grid = { ...this.grid, rowForm: modes[name] };
    queueMicrotask(() => this.gridRef.grid?.form.open(String(rows[0].id)));
  }

  ngAfterViewInit() { this.gridRef.grid?.form.open(String(rows[0].id)); }
}

bootstrapApplication(AppComponent);