Lattice Grid Buy a licence

demo D282

Data bars and icon sets as rules in Angular

Proportional bars and per-band glyphs painted by the rule engine, undoable and saved with a view

formatting rules: dataBar, iconSet

This grid paints proportional data bars and per-band icon sets from the same ordered rule list that drives its colour scales, and both can be undone and saved with a view. It turns a number into a length or a good, watch, act glyph you read at a glance, as live rules rather than a build step.

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 } 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';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [LatticeGridComponent],
  template: '<lattice-grid [config]="grid" style="display:block;height:480px"></lattice-grid>',
})
export class AppComponent {
  grid = {
    rowKey: 'id',
    toolPanel: { side: 'left', panels: ['formatting', 'columns', 'filters', 'views'] },
    // Rules keyed by column id. Data bars and icon sets are declarative, so
    // the same rules paint for a server-side export as for the screen.
    formatting: {
      revenue: [{ id: 'revenue-bar', dataBar: { from: 'minmax', colour: '#5b9bd5' } }],
      delta: [{ id: 'delta-bar', dataBar: { min: -40, max: 40, colour: '#1a7f4b', negativeColour: '#c0392b' } }],
      sla: [{ id: 'sla-icons', iconSet: { set: 'trafficLights', thresholds: [90, 98] } }],
      trend: [{ id: 'trend-icons', iconSet: { set: 'arrows', thresholds: [-5, 5] } }],
    },
    columns: [
      { field: 'service', title: 'Service', layout: { pin: 'start', width: 150 } },
      { field: 'region', title: 'Region', filter: { type: 'set' } },
      { field: 'revenue', title: 'Revenue', type: 'number', layout: { width: 200 }, format: { style: 'currency', currency: 'USD', decimals: 0 }, filter: { type: 'number' } },
      { field: 'delta', title: 'Change', type: 'number', layout: { width: 170 }, format: { decimals: 1, suffix: '%' } },
      { field: 'sla', title: 'SLA', type: 'number', layout: { width: 130 }, format: { decimals: 1, suffix: '%' } },
      { field: 'trend', title: 'Trend', type: 'number', layout: { width: 120 } },
    ],
    rows: [/* services: service, region, revenue, delta, sla, trend */],
  };
}

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

Data bars and icon sets that belong to the data

A data bar turns a number into a length you read at a glance, and an icon set turns it into a glyph that says good, watch, act. In Lattice Grid both are rules in the same ordered, per-column list that paints your colour scales, so a bar or an icon set is declared the way a threshold is: formatting: { revenue: [{ dataBar: { from: 'minmax' } }] } for a proportional bar, or { iconSet: { set: 'trafficLights', thresholds: [90, 98] } } for a per-band glyph. A bar can pin its own scale or derive it from the column, and a range that crosses zero grows both ways from a shared axis, growth to the right and contraction to the left in their own colours. Because a bar draws as a background gradient and an icon set as a background image, both sit behind the cell’s own text and need no extra element.

Reaching for the rule engine buys four things the visual keeps for free: it composes with a condition, so a bar can be painted only where another rule says it matters; it derives its bounds from the column over the rows on screen; it rides the undo timeline; and it travels in a saved view, so a person who arranges their grid keeps the bars and icons when they return. The same rule paints for a server-side export as for the browser, so a report generated on the server carries the identical bars and glyphs a reader saw on the page.

When do I use a formatting rule and when a runtime decoration?

Both the rule engine and the runtime decoration API (grid.columns.decorate) can draw a data bar or an icon set, and they are for two different jobs. Reach for a rule when the visual belongs to the data: a rule composes with your other conditions, derives its bounds from the column, rides the undo timeline, travels in a saved view, and paints the same for a server-side export as for the screen. Reach for a runtime decoration when the visual is a presentation choice you flip on after the grid is built and do not want saved with the view or placed on the undo timeline. Put simply: pick the rule when the formatting must survive a reload and reach an export; pick the decoration for a lighter touch you set on the page and clear again. Choosing on that one question keeps the two from feeling like the same feature offered twice.

How do I add a data bar or icon set to a column?

List it as a rule under the column in the formatting option: { dataBar: { from: 'minmax', colour: '#5b9bd5' } } draws a proportional bar across the column’s range, and { iconSet: { set: 'trafficLights', thresholds: [90, 98] } } places a glyph beside the value by the band it falls in. Pin a bar’s scale with min and max, or let from derive it from the column; name a built-in icon set (arrows, trafficLights, ratings) or supply your own glyphs. Because it is a rule, it is undoable, it is saved with the view, and it paints the same way for a server-side export as for the screen.