Lattice Grid Buy a licence

demo D91

Optimistic writes

The server disagrees, and the cell reverts with an explanation

edit: { commit, confirm }

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>
  // Stand-in for the write endpoint a real application would have. Resolve to
  // accept the write, throw to have the grid roll the cell back; the thrown
  // message becomes the reason on cell:reverted.
  const COMMIT_DELAY = 900;
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
  async function commit({ key, colId, value }) {
    await sleep(COMMIT_DELAY);
    const ordinal = Number(String(key).replace(/\D+/g, ''));
    if (Number.isFinite(ordinal) && ordinal % 5 === 0) {
      throw new Error(`${key} is locked by change control; ask them to release it.`);
    }
    if (colId === 'budget' && typeof value === 'number' && value > 50000) {
      throw new Error('Budgets above 50,000 need a second approver.');
    }
    if (colId === 'stage' && value === 'done') {
      throw new Error('A change is closed by the field engineer, not from here.');
    }
  }

  const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
    rowKey: 'id',
    selection: 'multiple',
    edit: {
      enabled: true,
      commit,
      confirm: 'auto',
      // The stale-write warning, set comfortably above the delay so a healthy
      // write is never the thing that trips it.
      pendingTimeout: COMMIT_DELAY * 4,
    },
    columns: [
      { field: 'id', title: 'Order', layout: { width: 120, pin: 'start' } },
      { field: 'reference', title: 'Reference', layout: { width: 130 } },
      { field: 'stage', title: 'Stage', filter: { type: 'set' }, edit: true },
      { field: 'circuits', title: 'Circuits', type: 'number', layout: { width: 110 }, edit: true },
      { field: 'budget', title: 'Budget', type: 'number', layout: { width: 140 },
        format: { style: 'currency', currency: 'GBP' }, total: 'sum', edit: true },
    ],
    rows,  // work orders
  });
</script>

Committing edits before the server confirms them

Optimistic writes let a grid apply an edit to the UI immediately, before the request that persists it has returned. A developer reaches for this when the round trip to the server is the slowest part of an edit interaction: a spreadsheet-style grid where every cell change fires a save, a form embedded in a data table, anything where waiting for a response before showing the new value would make typing feel laggy. Lattice Grid controls this with edit: { commit, confirm }: commit writes the value into the row the moment editing ends, and confirm is the callback that later reconciles that write against what the server accepted. When the server disagrees, whether over a stale row version, a server-side validation rule, or a conflicting write from another session, the cell reverts to its prior value and Lattice Grid surfaces the rejection reason from the confirm callback rather than failing silently. The revert targets only the rejected cell, so other pending edits in the same row or grid are unaffected. This keeps a JavaScript data grid responsive under real network latency while leaving the server the final word on what a row contains, and gives screen reader users a change announcement at the moment of reversion rather than a delayed, unexplained value swap.

What happens if the server rejects an optimistic edit?

The confirm callback in edit: { commit, confirm } receives the server’s response. If it reports rejection, Lattice Grid reverts the affected cell to its pre-edit value and exposes the reason the callback returned, so the interface can show why the write did not stick. Only the rejected cell reverts; other edits already committed elsewhere in the grid stay in place.