Lattice Grid Buy a licence

demo D212

Manufacturing and process in Angular

A machined bore with a tolerance driving capability, drifting in one shift

spec · grid.statistics.capability

This is a machined-bore dataset with a tolerance driving a capability figure, and the process drifting within a single shift. It shows manufacturing data judged against its spec in real time, so a drift out of tolerance shows as it happens.

Building…
Loading a live grid…

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, ViewChild, AfterViewInit } 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';

const columns = [
  { field: 'part', title: 'Part', layout: { pin: 'start', width: 120 } },
  { field: 'shift', title: 'Shift', filter: { type: 'set' } },
  // spec is the tolerance the capability figures are measured against.
  { field: 'bore', title: 'Bore', type: 'millimetres', total: 'median',
    spec: { lower: 9.5, upper: 10.8, target: 10 } },
  { field: 'speed', title: 'Spindle', type: 'rpm', total: 'avg' },
  { field: 'line', title: 'Line pressure', type: 'bar', total: 'p95' },
  { field: 'torque', title: 'Torque', type: 'torque', total: 'max' },
];

const rows = [/* measured parts */];



@Component({
  selector: 'app-root',
  standalone: true,
  imports: [LatticeGridComponent],
  template:
    '<lattice-grid [config]="grid" (grid-ready)="onReady($event)" (filter-changed)="render()" style="display:block;height:460px"></lattice-grid>' +
    '<div id="panel" style="display:flex;gap:14px;margin-top:10px;font:13px system-ui"></div>',
})
export class AppComponent implements AfterViewInit {
  @ViewChild(LatticeGridComponent) gridRef!: LatticeGridComponent;
  grid: any;

  private setup() {
    this.grid = {
      rowKey: 'id',
      toolPanel: { side: 'left', panels: ['columns', 'filters', 'statistics'] },
      columnDefaults: { filter: true },
      formatting: {
        bore: [
          { id: 'b-out', when: { op: 'notBetween', value: 9.5, value2: 10.8 }, style: { background: '#fbeceb' } },
          { id: 'b-z', when: { op: 'zAbove', value: 2 }, style: { background: '#fff4e5' } },
        ],
      },
      columns: columns,
      rows: rows,
    };
  }

  constructor() {
    this.setup();
  }

  ngAfterViewInit() {
    this.render();
  }

  onReady() {
    this.render();
  }

  // baseline fixes the limits on the first 40 readings, so a later tool-wear
  // drift separates Cpk from Ppk rather than widening the limits to absorb it.
  render() {
    const grid = this.gridRef && this.gridRef.grid;
    if (!grid) return;
    const c = grid.statistics.capability('bore', { baseline: 40 });
    const panel = document.getElementById('panel');
    if (!panel) return;
    const n = (v: unknown) => (typeof v === 'number' ? v.toFixed(2) : v);
    panel.innerHTML =
      '<span><strong>Cp</strong> ' + n(c.cp) + '</span>' +
      '<span><strong>Cpk</strong> ' + n(c.cpk) + '</span>' +
      '<span><strong>Pp</strong> ' + n(c.pp) + '</span>' +
      '<span><strong>Ppk</strong> ' + n(c.ppk) + '</span>' +
      '<span><strong>defect rate</strong> ' + n(c.defectRate) + '</span>';
  }
}

bootstrapApplication(AppComponent, {
  providers: [provideLattice({ createGrid })],
});