Lattice Grid Buy a licence

demo D139

The cell context menu

An item that writes is never offered on a cell that cannot be written

cell:contextmenu

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',
          selection: 'multiple',
          edit: { enabled: true },
          // Right-click a cell for a menu whose entries read the cell under the
          // pointer: the editable columns offer to edit, the read-only ones do not.
          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 } },
          ],
          rows,  // service records
        },
      };
    },
    template: '<lattice-grid v-bind="config" />',
  }).mount('#grid');
</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.