Data Grid Context Menu & Formatting
DataGridContextMenuPlugin provides a complete, task-oriented menu without requiring every grid to define copy, edit, inspection, row, filter, formatting, sizing, grouping, column-management, and export actions from scratch. It auto-installs ContextMenuPlugin, ColumnDialogPlugin, Column Hide support, the cell inspector, and the spreadsheet formatting runtime.
Open the four-framework standalone example
or browse its source in
revogrid-demos/pro-data-grid-context-menu.
Enable the preset
Section titled “Enable the preset”import { DataGridContextMenuPlugin } from '@revolist/revogrid-pro';
grid.plugins = [DataGridContextMenuPlugin];Installing the plugin enables its defaults. Set the property to false to keep the plugin registered while suppressing the preset:
grid.dataGridContextMenu = false;The preset is a prepended context-menu contribution. Existing rowContextMenu, columnContextMenu, and independent plugin contributions remain after it by default.
Customize by stable item ID
Section titled “Customize by stable item ID”Hide or disable one generated command without rebuilding its parent submenu:
grid.dataGridContextMenu = { hiddenItems: { 'row.delete': true, }, disabledItems: { 'row.duplicate': context => context.rows.length > 20, },};Resolvers receive a semantic DataGridContextMenuContext with the active surface, target rows, range, leaf columns, column group, and low-level menu context.
The surfaces are cell, rowHeader, rowGroup, columnHeader, and columnGroupHeader. Disable a whole surface with areas:
grid.dataGridContextMenu = { areas: { rowGroup: false },};Extend or replace generated items
Section titled “Extend or replace generated items”Use items for a simple extension. Use getItems when a surface needs complete replacement or transformation.
grid.dataGridContextMenu = { items: context => [{ id: 'app.audit', name: 'Open audit history', action: () => openAuditHistory(context.rows[0]?.model), }], getItems: (context, defaults) => context.surface === 'columnGroupHeader' ? [{ id: 'app.groupSummary', name: 'Open group summary' }] : defaults,};Set includeHostItems: false to suppress the application-provided base menu on enabled preset surfaces. Other plugin contributions still compose independently.
Command lifecycle and remote data
Section titled “Command lifecycle and remote data”Every built-in command first emits a cancelable datagrid-context-menu-command event:
grid.addEventListener('datagrid-context-menu-command', event => { if (event.detail.id === 'row.delete' && usesRemoteRows) { event.preventDefault(); void deleteRowsOnServer(event.detail.context.rows); }});A commandHandlers entry also replaces local behavior:
grid.dataGridContextMenu = { commandHandlers: { 'row.delete': context => api.deleteRows( context.rows.map(row => row.model.id), ), },};Local row mutation is hidden for remote/server-grouped runtimes until a handler is provided. Clipboard permission and export failures emit datagrid-context-menu-error; Cut clears cells only after the clipboard write succeeds.
Optional capabilities
Section titled “Optional capabilities”Commands appear only when their runtime exists. Add the matching plugin to expose filtering, Excel export, row selection, column auto-size, column collapse, tree, or server-grouping actions. Set unavailableItems: 'disable' to show unavailable commands in a disabled state instead.
grid.dataGridContextMenu = { unavailableItems: 'disable', rowPinning: true,};Row pinning is opt-in. Column insertion, duplication, and deletion are also opt-in and require an application factory so every new column receives a unique schema key:
grid.dataGridContextMenu = { columnSchema: { createColumn({ action, sourceColumn }) { return { ...sourceColumn, prop: `${String(sourceColumn.prop)}-${action}-${crypto.randomUUID()}`, }; }, },};Spreadsheet-style formatting
Section titled “Spreadsheet-style formatting”Cell and column-header menus include a type-aware Format submenu. Native
numeric values expose Number, Currency, Accounting, Percentage, and Scientific
presets; native Date values expose Date, Date & time, and Time. More
formats… opens a separate Format Cells dialog for locale, decimal and date
styles, font and fill, alignment, wrapping, borders, and a live preview.
See Format Cells for the complete popup guide, including selection behavior, stable row identity, render-time application, direct plugin usage, and runtime persistence limits.
Formatting changes presentation only. Raw source values used by editors, sorting, filtering, and formulas are not rewritten. Cell commands target the active range; column-header commands create a true column formatting default.
Map application column types explicitly when their values do not carry native
number or Date types:
grid.dataGridContextMenu = { formatting: { locale: 'en-GB', currencies: ['GBP', 'EUR', 'USD'], getRowKey: row => row.id, columnTypeKinds: { money: 'number', applicationDate: 'date', }, },};Set formatting: false to remove the whole formatting submenu. Formatting
commands respect grid and per-cell readonly rules. Value presets preserve
authored custom cell templates; the rich dialog can still compose appearance
through cellProperties without replacing interactive content.
Inspect raw cell and column data
Section titled “Inspect raw cell and column data”Inspect cell opens a compact read-only popup for the exact invoked cell. It
shows the column label and property, row dimension and authored source index,
plus the raw value and its JavaScript type. The bounded serializer displays
dates, undefined, bigint, symbols, functions, accessors, and circular
references as selectable JSON-like inspection text without invoking getters or
toJSON.
Full enumerable row snapshots are opt-in because source models can contain hidden or internal fields. Inspect column is available from leaf column headers and shows the property, pinned dimension, visible and physical indexes, type, readonly mode, sort order, filter configuration, rendered width, and authored width bounds. The complete resolved column definition is also opt-in because schema objects can contain private application metadata.
Limits and an application redaction hook are available when complete row or column inspection is appropriate:
grid.dataGridContextMenu = { inspection: { includeRowData: true, includeColumnData: true, serialization: { maxDepth: 5, maxEntries: 100, maxOutputLength: 20_000 }, redact(value, { kind }) { return kind === 'row' || kind === 'column' ? redactPrivateFields(value) : value; }, localeText: { title: 'Cell details' }, },};The limits bound recursive traversal and rendered output after JavaScript has
discovered an object’s own keys. They are not a sandbox for hostile Proxy traps
or extremely wide objects; use redact to replace untrusted complex values.
Both inspectors remain available for readonly cells and readonly grids. Hide
them like any other built-in item with hiddenItems: { 'cell.inspect': true, 'column.inspect': true }, or replace their behavior through the matching
commandHandlers entry.