demo D139
The cell context menu in React
An item that writes is never offered on a cell that cannot be written
cell:contextmenu
This grid offers per-value actions, copy, clear, comment or edit, on right-clicking a cell, and never offers a write action on a cell that cannot be written. It puts the right actions under the pointer, so the menu matches what a reader can actually do to that cell.
This is the React version. The grid mounts through the createLatticeGrid adapter, which takes its configuration as ordinary props and hands back the live grid through a ref. The grid below is the same one every other tab runs.
The configuration
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">
<div id="grid"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { createGrid } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/react.esm.min.js';
const LatticeGrid = createLatticeGrid({ React, createGrid });
// The cell menu opens on right-click. Its paste and edit actions appear only
// where a cell is editable, which is why the columns here differ.
const columns = [
{ field: 'service', title: 'Service (read only)', layout: { pin: 'start', width: 190 } },
{ field: 'team', title: 'Team (read only)', layout: { width: 150 } },
{ field: 'owner', title: 'Owner (editable)', edit: true, layout: { width: 170 } },
{ field: 'region', title: 'Region (editable)', edit: true, layout: { flex: 1, min: 180 } },
{ field: 'instances', title: 'Instances (edit: false)', type: 'number', edit: false, layout: { width: 180 } },
];
const rows = [/* service records */];
function App() {
return (
<LatticeGrid
rowKey="id"
selection="multiple"
edit={{ enabled: true }}
columns={columns}
rows={rows}
style={{ height: '540px' }}
/>
);
}
createRoot(document.getElementById('grid')).render(<App />);
</script>
Right-clicking a cell for a menu built from what that cell allows
A cell context menu is the natural place for per-value actions: copy, clear, comment, or edit, offered against the record under the pointer rather than as a permanent toolbar entry. The difficult part is not opening the menu but deciding its contents, since an item that writes is never offered on a cell that cannot be written. A read-only column, a cell disabled by a per-row rule, or a value a viewer lacks permission to change must each produce a shorter menu, not a full one with a disabled entry. Any JavaScript data grid handling mixed editable and locked columns needs this filtering done before the menu paints, not as a visual afterthought.
Lattice Grid exposes the interaction through the cell:contextmenu event, fired with the row, column, and value under the pointer, so a host application can inspect the same edit rules the grid uses and build a menu matching what the cell will accept. The default menu closes on outside click, on Escape, and once an item is chosen, and it is reachable without a mouse: the context-menu key and Shift+F10 open it against the focused cell. Menu construction runs once per invocation rather than being pre-built for every cell, so a wide grid with thousands of visible cells pays the permission-check cost only for the cell actually right-clicked.
Why does a cell’s context menu sometimes show fewer options than another cell in the same column?
Menu contents are computed per cell at the moment of the cell:contextmenu event, not fixed per column. A row-level rule, a permission check, or a value that fails validation can each remove a write action, so two cells in one column can legitimately offer different menus depending on the record behind them.