Lattice Grid Buy a licence

demo D27

JSON and structured values

A nested object in a cell, summarised inline and expandable

type: 'json'

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.min.css">
<style>
  #grid > div { height: 540px; }
</style>
<div id="grid"></div>

<script type="module">
  import * as Vue from 'https://esm.sh/vue@3';
  import { createGrid } from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.esm.min.js';
  import createLatticeGrid from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/modules/vue.esm.min.js';

  const LatticeGrid = createLatticeGrid({ vue: Vue, createGrid });

  Vue.createApp({
    components: { LatticeGrid },
    data() {
      return {
        config: {
          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: 260, pin: 'start' } },
            {
              field: 'config', title: 'Config', type: 'json', layout: { flex: 1, min: 260 },
              // Short objects print in full; anything longer collapses to a count,
              // because a cell that wraps six lines of JSON is not a cell. The
              // full document is on the tooltip and in the editor.
              cell: {
                props: { inlineLimit: 44 },
                tooltip: (p) => {
                  try { return JSON.stringify(p.value, null, 2); } catch { return ''; }
                },
              },
            },
            {
              field: 'config', id: 'interfaces', title: 'Interfaces', type: 'json', layout: { width: 200 },
              value: { deps: ['config'], pure: true, compute: (d) => d.config?.interfaces ?? null },
            },
            {
              id: 'asn', title: 'BGP ASN', type: 'number', layout: { width: 130 },
              // Pulling a leaf out of the document gives you a real number column:
              // it sorts, it filters as a range, it totals. The object stays whole
              // underneath.
              value: { deps: ['config'], pure: true, compute: (d) => d.config?.bgp?.asn ?? null },
              filter: { type: 'number' },
            },
            {
              id: 'mtu', title: 'Max MTU', type: 'number', layout: { width: 130 },
              value: {
                deps: ['config'], pure: true,
                compute: (d) => {
                  const list = d.config?.interfaces ?? [];
                  return list.length ? Math.max(...list.map((i) => i.mtu)) : null;
                },
              },
            },
            {
              id: 'snmp', title: 'SNMP', layout: { width: 110 },
              value: { deps: ['config'], pure: true, compute: (d) => d.config?.snmp?.version ?? null },
              filter: { type: 'set' },
            },
            { field: 'hardware', title: 'Hardware', type: 'json', layout: { width: 240 } },
          ],
          rows,  // nodes, each with a nested config object
        },
      };
    },
    template: '<lattice-grid v-bind="config" />',
  }).mount('#grid');
</script>

Rendering nested JSON in a grid cell

Source data is not always flat. An order row might carry a shipping address as a nested object, or a user record might embed a permissions map, and a JavaScript data grid that only accepts scalars forces a flattening step before the data can be displayed at all. Lattice Grid’s type: 'json' column renders that structure directly: the cell shows a compact inline summary of the object, and expands on demand to a formatted, indented view of the full value, so nesting depth is never lost to a stringified blob. A developer reaches for this type wherever an API response is stored as-is rather than normalised into separate columns, which keeps the column definition stable even when the shape of the nested data grows a new key.

Because the summary is generated from the object rather than pre-rendered per row, a json column pays no layout cost until a cell is actually expanded: collapsed rows contribute a single-line label to the row height calculation, so a grid holding thousands of records with deeply nested payloads scrolls at the same frame rate as one holding plain strings. Expansion is keyboard-operable, so the nested view is reachable without a pointer, which matters for any grid built to pass an accessibility audit rather than merely look right under a mouse.

How do you display a JSON object in a data grid cell?

Set the column’s type to 'json'. Lattice Grid shows a condensed one-line summary of the object in the collapsed cell and an indented, formatted view when the cell is expanded, so nested values stay inspectable without a custom renderer or a separate detail panel.