Lattice Grid Buy a licence

demo D32

The renderer gallery

Every built-in renderer in one grid, each in its own column

cell: { render: … }

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.css">
<script src="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.js"></script>

<div id="grid" style="height: 540px"></div>

<script>
  const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
    rowKey: 'id',
    // Two lines and a QR symbol need the room; at standard density both are
    // clipped, which would make the gallery an argument against itself.
    density: 'comfortable',
    selection: 'multiple',
    toolPanel: {
      side: 'left',
      panels: ['columns', 'filters', 'views', 'quick'],
      actions: ['undo', 'redo', 'export', 'restore', 'maximise'],
      exportName: 'lattice-demo',
    },
    columns: [
      { field: 'service', title: 'Service', layout: { pin: 'start', width: 190 },
        cell: { render: 'twoline', props: { secondary: 'team' } } },
      { field: 'avatar', title: 'image', type: 'image', layout: { width: 70 },
        sort: { enabled: false }, cell: { props: { shape: 'circle', size: 26, alt: 'Owner' } } },
      { field: 'status', title: 'pill', layout: { width: 110 },
        cell: { render: 'pill', props: { variant: {
          map: { healthy: 'success', degraded: 'warning', failing: 'danger' },
          default: 'neutral',
        } } } },
      { field: 'severity', title: 'icon', layout: { width: 110 },
        cell: { render: 'icon', props: { name: {
          critical: 'danger', high: 'warning', normal: 'info', low: 'check',
        } } } },
      { field: 'colour', title: 'colour', layout: { width: 120 },
        cell: { render: 'colour', props: { uppercase: true } } },
      { field: 'rating', title: 'rating', type: 'number', layout: { width: 130 },
        cell: { render: 'rating', props: { max: 5, allowHalf: true } } },
      { field: 'completion', title: 'progress', type: 'number', layout: { width: 150 },
        format: { suffix: '%' }, cell: { render: 'progress' } },
      { field: 'attainment', title: 'bullet', type: 'number', layout: { width: 150 },
        cell: { render: 'bullet', props: { min: 0, max: 120, bands: [60, 90], target: 85 } } },
      { field: 'utilisation', title: 'gauge', type: 'number', layout: { width: 110 },
        cell: { render: 'gauge', props: { min: 0, max: 100 } } },
      { id: 'traffic-line', field: 'traffic', title: 'line', layout: { width: 130 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'line' } },
      { id: 'latency-area', field: 'latency', title: 'area', layout: { width: 130 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'area' } },
      { id: 'spread-column', field: 'spread', title: 'column', layout: { width: 130 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'column' } },
      { id: 'streak-winloss', field: 'streak', title: 'winloss', layout: { width: 120 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'winloss' } },
      { id: 'mix-pie', field: 'mix', title: 'pie', layout: { width: 90 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'pie' } },
      { id: 'mix-donut', field: 'mix', title: 'donut', layout: { width: 90 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'donut' } },
      { id: 'mix-stacked', field: 'mix', title: 'stacked', layout: { width: 140 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'stacked' } },
      { id: 'spread-range', field: 'spread', title: 'range', layout: { width: 140 },
        sort: { enabled: false }, filter: { enabled: false }, cell: { render: 'range' } },
      { field: 'price', title: 'delta', type: 'number', layout: { width: 130 },
        format: { style: 'currency', currency: 'USD', decimals: 2 },
        cell: { render: 'delta', props: { mode: 'against', against: 'previousClose' } } },
      { field: 'url', title: 'link', layout: { width: 220 },
        cell: { render: 'link', props: { target: '_blank' } } },
      { field: 'ticket', title: 'qrcode', layout: { width: 80 },
        sort: { enabled: false }, cell: { render: 'qrcode', props: { size: 34, margin: 2 } } },
      { field: 'cost', title: 'skeleton', type: 'number', layout: { width: 130 },
        sort: { enabled: false }, cell: { render: 'skeleton' } },
    ],
    rows,  // rendering demo rows
  });
</script>

Choosing a cell renderer without writing one

A cell renderer is the function that turns a stored value into what actually appears in a cell: text, a pill, a bar, a sparkline, a rating, a two-line block, and the rest. A developer reaches for the gallery view of a JavaScript data grid at the point where a column list stops being an abstraction and becomes a decision: which of the built-in shapes already covers this field, and which one still needs a custom renderer. Lattice Grid sets the renderer per column with cell: { render: … }, so a status column can take render: 'pill' and a trend column render: 'line' in the same configuration, each drawing into its own cell without touching how neighbouring columns are typed, sorted or filtered. Because every renderer runs inside the same recycled cell pool as plain text, switching a column from a string to a sparkline or a progress bar changes what is drawn, not how many DOM nodes the grid holds per visible row, so a wide column set at full renderer variety scrolls at the same frame budget as a column of plain numbers. The gallery lays out one renderer per column deliberately, so each can be inspected in isolation and compared against its neighbours before it is picked for a real dataset.

What renderer options does Lattice Grid ship with?

The built-in set covers pills and variants, progress and bullet, sparklines, win-loss and gauge and range, pie and donut, stacked bars, delta indicators, ratings, colours and icons, images and QR codes, two-line cells, and skeleton loading. Each is a value for cell.render, chosen per column, with a custom renderer available for anything the built-in set does not cover.