Lattice Grid Buy a licence

demo D05

Column defaults and presets in htmx

Declaring shared column behaviour once, used by six columns

columnDefaults · columnPresets

This grid declares shared column behaviour once, then lets six columns inherit it: alignment, a comparator, a formatter and whether a column sorts at all. It keeps a wide configuration short and consistent, so you set a rule in one place instead of repeating it on every column.

Building…
Loading a live grid…

This is the htmx version. A server-rendered table is upgraded in place, so the page is readable before any script runs and gains the full grid when the module loads, which suits a progressively enhanced app.

The configuration

<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">

<!-- A real, server-rendered table: readable with JavaScript off. data-field on
     each header names the column that cell becomes, and data-id on each row is
     the key the grid carries it under. -->
<table id="column-defaults-table" data-lattice-grid>
  <thead>
    <tr>
      <th data-field="service">Service</th>
      <th data-field="team">Team</th>
      <th data-field="monthlyCost">Monthly cost</th>
      <th data-field="budget">Budget</th>
      <th data-field="p50Ms">p50</th>
      <th data-field="p95Ms">p95</th>
      <th data-field="p99Ms">p99</th>
    </tr>
  </thead>
  <tbody>
    <tr data-id="1"><td>svc-00001</td><td>Search</td><td>37920.55</td><td>20036</td><td>27</td><td>140</td><td>3906</td></tr>
    <tr data-id="2"><td>svc-00002</td><td>Mobile</td><td>30070.04</td><td>56591.85</td><td>9</td><td>427</td><td>1281</td></tr>
    <tr data-id="3"><td>svc-00003</td><td>Identity</td><td>36278.48</td><td>8543.17</td><td>57</td><td>476</td><td>2637</td></tr>
    <!-- the rest of the rows, rendered by your server -->
  </tbody>
</table>

<script type="module">
  import { hydrateTable } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/htmx.esm.min.js';

  // The markup carries the rows; a server-rendered table's column types are
  // declared in the config hydrateTable takes. The grid replaces the table
  // where it stood.
  const grid = hydrateTable(document.getElementById('column-defaults-table'), {
    // Turned on for every column once, rather than repeated on each.
    columnDefaults: { filter: true, sort: true },
    // Named bundles of column settings. A column says `preset: 'money'` instead
    // of repeating the type, the format and the total.
    columnPresets: {
      money: {
        type: 'number',
        format: { style: 'currency', currency: 'USD' },
        total: 'sum',
        layout: { width: 150 },
      },
      latency: { type: 'number', layout: { width: 100 }, format: { suffix: ' ms' } },
    },
    columns: [
      { field: 'service', title: 'Service', layout: { pin: 'start', width: 140 } },
      { field: 'team', title: 'Team' },
      { field: 'monthlyCost', title: 'Monthly cost', preset: 'money' },
      { field: 'budget', title: 'Budget', preset: 'money' },
      { field: 'p50Ms', title: 'p50', preset: 'latency' },
      { field: 'p95Ms', title: 'p95', preset: 'latency' },
      { field: 'p99Ms', title: 'p99', preset: 'latency' },
    ],
  });
</script>

Shared column behaviour with defaults and presets

columnDefaults sets the properties every column inherits before its own definition overrides them: alignment, a comparator, a formatter, whether the column is sortable at all. A developer reaches for it once a grid grows past three or four columns and the same type: 'number' or align: 'right' starts repeating across every one of them, because a JavaScript data grid with thirty numeric columns should not need thirty repeated option blocks to behave consistently. columnPresets goes a step further, naming a bundle of options once and applying that name to any column that wants it, so a 'currency' preset can set the formatter, alignment and width in one place and six columns can each declare preset: 'currency' and nothing else. Change the preset and all six move together; that single point of change is the practical argument for defaults over per-column repetition, not just less typing. Defaults and presets both resolve before a column’s own explicit settings, so a column can take everything from a preset and override just one field, such as width, without redeclaring the rest. Resolution happens once when the grid initialises rather than per cell, so the saving is in configuration size and consistency, not render cost.

How do I avoid repeating the same column options in a data grid?

Set the shared options once in columnDefaults, or name a bundle of them with columnPresets and reference that name from each column. Columns still declare their own field and anything that differs, but formatter, alignment, sortability and similar options only need writing once. Lattice Grid merges defaults, the named preset, and the column’s own settings in that order before the grid renders.