Lattice Grid Buy a licence

demo D29

Multi-value cells

Tags in one cell, with containsAny and containsAll filtering

multiple: true

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',
    toolPanel: {
      side: 'left',
      panels: ['columns', 'filters', 'views', 'quick'],
      actions: ['undo', 'redo', 'export', 'restore', 'maximise'],
      exportName: 'lattice-demo',
    },
    columns: [
      { field: 'hostname', title: 'Hostname', layout: { width: 280, pin: 'start' } },
      {
        field: 'tags', title: 'Tags', layout: { flex: 1, min: 240 },
        // `multiple: true` makes the cell an array rather than a value, and
        // brings the set operators with it: containsAny, containsAll and
        // containsNone, rather than equality against a joined string.
        lookup: { options: TAGS, multiple: true, separator: ', ' },
        cell: { decoration: 'pill' },
      },
      {
        field: 'tags', id: 'count', title: 'Tag count', type: 'number', layout: { width: 130 },
        value: { deps: ['tags'], pure: true, compute: (d) => (Array.isArray(d.tags) ? d.tags.length : 0) },
        total: 'avg',
      },
      {
        id: 'inScope', title: 'In audit scope', type: 'boolean', layout: { width: 150 },
        // containsAll, written out. The filter below does the same thing to
        // the rows; this does it to a value.
        value: {
          deps: ['tags'], pure: true,
          compute: (d) => {
            const t = Array.isArray(d.tags) ? d.tags : [];
            return t.includes('pci') && t.includes('gdpr');
          },
        },
      },
      {
        field: 'site', title: 'Site', type: 'lookup', layout: { width: 180 },
        lookup: { options: SITES, unknownLabel: 'decommissioned' },
      },
      { field: 'ports', title: 'Ports', type: 'number', layout: { width: 110 } },
    ],
    // containsAny, containsAll and containsNone match nothing unless the memory
    // source is in its columnar store. Raising the threshold keeps the
    // operators working across the whole dataset.
    source: { mode: 'memory', columnarBelow: 2_000_000 },
    // Lands filtered, so the operator is visible rather than described. Clear
    // it from the filters panel to get the other rows back.
    state: {
      filters: { op: 'and', conditions: [{ col: 'tags', op: 'containsAll', value: ['pci', 'gdpr'] }] },
    },
    rows,  // nodes, each with an array of tags
  });
</script>

Storing several values in one cell with multi-value columns

A multi-value cell holds more than one entry against a single row and column, the pattern behind tags, labels, skills and any field where a record can belong to several categories at once rather than exactly one. A developer reaches for it whenever a plain lookup column is too narrow for the data: a support ticket with three labels, a contact with two roles, a product in four categories. Lattice Grid turns a column into this shape with multiple: true, which changes how the cell reads and renders a value from a single code to an array of codes, each shown as its own chip within the cell, and changes how the filter menu behaves to match. Filtering follows the same split a reader would expect: containsAny matches a row if it carries at least one of the selected values, containsAll matches only rows carrying every one of them, and the two give different result sets over the same tag column whenever a row holds more than one tag. Rendering stays cheap at scale because each chip is a plain DOM node inside a recycled cell rather than a nested component, so a multi-value column in a JavaScript data grid scrolling past thousands of rows pays no more per row than the number of chips actually on screen.

How do you filter a column that holds several values per row?

Set multiple: true on the column so each cell stores an array rather than a single value, then choose the filter operator: containsAny for rows matching at least one selected tag, containsAll for rows matching every selected tag. Lattice Grid applies whichever operator is set against the full array on each row.