Context menu
The context menu provides cell-level actions accessible by right-clicking. This page lists all available menu items and their configuration keys.
Context menu with default options
Enable the context menu with the default configuration:
contextMenu: true,To see the context menu, right-click on a cell. On touch devices, long-press a cell to open the context menu.
import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.registerAllModules();
const container = document.querySelector('#example1');
new Handsontable(container, { data: [ ['', 'Tesla', 'Nissan', 'Toyota', 'Honda', 'Mazda', 'Ford'], ['2017', 10, 11, 12, 13, 15, 16], ['2018', 10, 11, 12, 13, 15, 16], ['2019', 10, 11, 12, 13, 15, 16], ['2020', 10, 11, 12, 13, 15, 16], ['2021', 10, 11, 12, 13, 15, 16], ], rowHeaders: true, colHeaders: true, contextMenu: true, height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.registerAllModules();
const container = document.querySelector('#example1')!;
new Handsontable(container, { data: [ ['', 'Tesla', 'Nissan', 'Toyota', 'Honda', 'Mazda', 'Ford'], ['2017', 10, 11, 12, 13, 15, 16], ['2018', 10, 11, 12, 13, 15, 16], ['2019', 10, 11, 12, 13, 15, 16], ['2020', 10, 11, 12, 13, 15, 16], ['2021', 10, 11, 12, 13, 15, 16], ], rowHeaders: true, colHeaders: true, contextMenu: true, height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});Context menu with selected options
You can define the items in the menu by passing the contextMenu option as an array of keys:
| Key | Action and required plugins |
|---|---|
row_above | Insert a row above |
row_below | Insert a row below |
col_left | Insert a column to the left |
col_right | Insert a column to the right |
--------- | Add a separator to the items in the menu |
remove_row | Remove the selected row |
remove_col | Remove the selected column |
clear_column | Delete the data of the selected columns |
undo | Undo the last action. Requires: UndoRedo |
redo | Redo the last action. Requires: UndoRedo |
make_read_only | Make the selected cells read-only |
alignment | Align the text in the cell |
cut | Cut the contents of the selected cells to the system clipboard. Requires: CopyPaste |
copy | Copy the contents of the selected cells to the system clipboard. Requires: CopyPaste |
copy_with_column_headers | Copy the contents of the selected cells and their nearest column headers. Requires: CopyPaste with copyColumnHeaders set to true |
copy_with_column_group_headers | Copy the contents of the selected cells and all their related column headers. Requires: NestedHeaders and CopyPaste with copyColumnGroupHeaders set to true |
copy_column_headers_only | Copy the contents of column headers that are nearest to the selected cells. Requires: CopyPaste with copyColumnHeadersOnly set to true |
freeze_column | Freeze the selected column. Requires: ManualColumnFreeze |
unfreeze_column | Unfreeze the selected column. Requires: ManualColumnFreeze |
borders | Add borders around the selected cells. Requires: CustomBorders |
commentsAddEdit | Add or edit a comment. Requires: Comments |
commentsRemove | Remove the comment. Requires: Comments |
commentsReadOnly | Make the comment read-only. Requires: Comments |
mergeCells | Merge or unmerge the selected cells. Requires: MergeCells |
add_child | Insert a child row. Requires: NestedRows |
detach_from_parent | Detach the selected row from its parent row. Requires: NestedRows |
hidden_columns_hide | Hide the selected columns. Requires: HiddenColumns |
hidden_columns_show | Show the hidden columns. Requires: HiddenColumns |
hidden_rows_hide | Hide the selected rows. Requires: HiddenRows |
hidden_rows_show | Show hidden rows. Requires: HiddenRows |
filter_by_condition | Add the first filter condition. Requires: Filters |
filter_by_condition2 | Add the second filter condition. Requires: Filters |
filter_operators | Select a filter parameter. Requires: Filters |
filter_by_value | Add a filter value. Requires: Filters |
filter_action_bar | Apply the configured filter. Requires: Filters |
export_file | Open the Export submenu with “To CSV” and “To Excel” items. Requires: ExportFile. The Excel item is hidden when no XLSX engine is configured. |
To see the context menu, right-click on a cell. On touch devices, long-press a cell to open the context menu.
import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.registerAllModules();
const container = document.querySelector('#example2');
new Handsontable(container, { data: [ ['', 'Tesla', 'Nissan', 'Toyota', 'Honda', 'Mazda', 'Ford'], ['2017', 10, 11, 12, 13, 15, 16], ['2018', 10, 11, 12, 13, 15, 16], ['2019', 10, 11, 12, 13, 15, 16], ['2020', 10, 11, 12, 13, 15, 16], ['2021', 10, 11, 12, 13, 15, 16], ], rowHeaders: true, colHeaders: true, contextMenu: ['row_above', 'row_below', 'remove_row', 'clear_column'], height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.registerAllModules();
const container = document.querySelector('#example2')!;
new Handsontable(container, { data: [ ['', 'Tesla', 'Nissan', 'Toyota', 'Honda', 'Mazda', 'Ford'], ['2017', 10, 11, 12, 13, 15, 16], ['2018', 10, 11, 12, 13, 15, 16], ['2019', 10, 11, 12, 13, 15, 16], ['2020', 10, 11, 12, 13, 15, 16], ['2021', 10, 11, 12, 13, 15, 16], ], rowHeaders: true, colHeaders: true, contextMenu: ['row_above', 'row_below', 'remove_row', 'clear_column'], height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});Context menu with a fully custom configuration
To fully customize the context menu, set contextMenu to an object with an items property. Each key in items identifies one menu entry. The value can be:
- A predefined item key string such as
'row_above'— includes the built-in item unchanged. - The string
'---------'— inserts a horizontal separator line. - A configuration object — defines a custom item or overrides a predefined one.
This means you can freely mix built-in items with custom ones in the same menu:
contextMenu: { // Optional: a shared callback fired on every item click. callback(key, selection, clickEvent) { console.log(key, selection, clickEvent); }, items: { row_above: {}, // predefined item, unchanged sp1: '---------', // separator row_below: { name: 'Click to add row below', // override a predefined item's label }, myOption: { // fully custom item name: 'My custom action', callback() { /* ... */ }, }, },},The top-level object also accepts a uiContainer property (an HTMLElement) to control which DOM element the context menu is appended to.
Menu item configuration options
Each configuration object in items can have these properties:
| Option | Description |
|---|---|
key | The unique identifier for the item. For top-level items, this is the key of the items object (for example 'row_above' or 'myOption'). For submenu items, it must follow the parent_key:child_key format (for example 'colors:red'). |
name | The label shown in the menu. Can be a string or a function returning a string. Supports HTML. When a function, this refers to the Handsontable instance. |
disabled | Whether the item is grayed out and non-clickable. Can be a boolean or a function returning a boolean. When a function, this refers to the Handsontable instance. |
hidden | Whether the item is hidden from the menu entirely. Can be a boolean or a function returning a boolean. When a function, this refers to the Handsontable instance. |
callback | A function called when the item is clicked. Receives key, selection, and clickEvent as arguments. |
submenu | Defines a nested submenu. Takes an object with an items array. Each submenu item’s key must follow the parent_key:child_key format. |
renderer | A custom function for rendering the item’s HTML. Must return an HTMLElement. |
disableSelection | When true, hovering over the item does not highlight it. |
isCommand | When false, clicking the item does not execute a command or close the menu. |
The following example shows how to:
- Add a shared callback for all options
- Dynamically disable an option
- Override the label of a predefined option
- Add a fully custom option with its own callback
- Add a custom option with a submenu
- Use a custom renderer
To see the context menu, right-click on a cell. On touch devices, long-press a cell to open the context menu.
import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.registerAllModules();
const contextMenuSettings = { callback(key, selection, clickEvent) { // Common callback for all options console.log(key, selection, clickEvent); }, items: { row_above: { disabled() { // `disabled` can be a boolean or a function // Disable option when first row was clicked return this.getSelectedLast()?.[0] === 0; // `this` === hot }, }, // A separator line can also be added like this: // 'sp1': { name: '---------' } // and the key has to be unique sp1: '---------', row_below: { name: 'Click to add row below', // Set custom text for predefined option }, about: { // Own custom option name() { // `name` can be a string or a function return '<b>Custom option</b>'; // Name can contain HTML }, hidden() { // `hidden` can be a boolean or a function // Hide the option when the first column was clicked return this.getSelectedLast()?.[1] == 0; // `this` === hot }, callback() { // Callback for specific option setTimeout(() => { alert('Hello world!'); // Fire alert after menu close (with timeout) }, 0); }, }, colors: { // Own custom option name: 'Colors...', submenu: { // Custom option with submenu of items items: [ { // Key must be in the form 'parent_key:child_key' key: 'colors:red', name: 'Red', callback() { setTimeout(() => { alert('You clicked red!'); }, 0); }, }, { key: 'colors:green', name: 'Green' }, { key: 'colors:blue', name: 'Blue' }, ], }, }, credits: { // Own custom property // Custom rendered element in the context menu renderer() { const elem = document.createElement('marquee');
elem.style.cssText = 'background: lightgray; color: #222222;'; elem.textContent = 'Brought to you by...';
return elem; }, disableSelection: true, isCommand: false, // Prevent clicks from executing command and closing the menu }, },};
const container = document.querySelector('#example3');
new Handsontable(container, { data: [ ['', 'Tesla', 'Nissan', 'Toyota', 'Honda', 'Mazda', 'Ford'], ['2017', 10, 11, 12, 13, 15, 16], ['2018', 10, 11, 12, 13, 15, 16], ['2019', 10, 11, 12, 13, 15, 16], ['2020', 10, 11, 12, 13, 15, 16], ['2021', 10, 11, 12, 13, 15, 16], ], rowHeaders: true, colHeaders: true, licenseKey: 'non-commercial-and-evaluation', height: 'auto', contextMenu: contextMenuSettings, autoWrapRow: true, autoWrapCol: true,});import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';import { DetailedSettings, MenuItemConfig } from 'handsontable/plugins/contextMenu';
// Register all Handsontable's modules.registerAllModules();
const contextMenuSettings: DetailedSettings = { callback(key, selection, clickEvent) { // Common callback for all options console.log(key, selection, clickEvent); }, items: { row_above: { disabled() { // `disabled` can be a boolean or a function // Disable option when first row was clicked return this.getSelectedLast()?.[0] === 0; // `this` === hot }, }, // A separator line can also be added like this: // 'sp1': { name: '---------' } // and the key has to be unique sp1: '---------' as MenuItemConfig, row_below: { name: 'Click to add row below', // Set custom text for predefined option }, about: { // Own custom option name() { // `name` can be a string or a function return '<b>Custom option</b>'; // Name can contain HTML }, hidden() { // `hidden` can be a boolean or a function // Hide the option when the first column was clicked return this.getSelectedLast()?.[1] == 0; // `this` === hot }, callback() { // Callback for specific option setTimeout(() => { alert('Hello world!'); // Fire alert after menu close (with timeout) }, 0); }, }, colors: { // Own custom option name: 'Colors...', submenu: { // Custom option with submenu of items items: [ { // Key must be in the form 'parent_key:child_key' key: 'colors:red', name: 'Red', callback() { setTimeout(() => { alert('You clicked red!'); }, 0); }, }, { key: 'colors:green', name: 'Green' }, { key: 'colors:blue', name: 'Blue' }, ], }, }, credits: { // Own custom property // Custom rendered element in the context menu renderer() { const elem = document.createElement('marquee');
elem.style.cssText = 'background: lightgray; color: #222222;'; elem.textContent = 'Brought to you by...';
return elem; }, disableSelection: true, // Prevent mouseoever from highlighting the item for selection isCommand: false, // Prevent clicks from executing command and closing the menu }, },};
const container = document.querySelector('#example3')!;
new Handsontable(container, { data: [ ['', 'Tesla', 'Nissan', 'Toyota', 'Honda', 'Mazda', 'Ford'], ['2017', 10, 11, 12, 13, 15, 16], ['2018', 10, 11, 12, 13, 15, 16], ['2019', 10, 11, 12, 13, 15, 16], ['2020', 10, 11, 12, 13, 15, 16], ['2021', 10, 11, 12, 13, 15, 16], ], rowHeaders: true, colHeaders: true, licenseKey: 'non-commercial-and-evaluation', height: 'auto', contextMenu: contextMenuSettings, autoWrapRow: true, autoWrapCol: true,});Related keyboard shortcuts and gestures
| Windows | macOS | Action | Excel | Sheets |
|---|---|---|---|---|
| Ctrl+Shift+\ or Shift+F10 | ⌘+⇧+\ or ⇧+F10 | Open the context menu | ✗ | ✓ |
| Long-press (touch devices) | Long-press (touch devices) | Open the context menu | ✗ | ✓ |
| Arrow keys | Arrow keys | Move one available menu item up, down, left, or right | ✓ | ✓ |
| Page Up | Page Up | Move to the first visible item of the context menu or submenu | ✓ | ✗ |
| Page Down | Page Down | Move to the last visible item of the context menu or submenu | ✓ | ✗ |
| Escape | Escape | Close the context menu or submenu | ✓ | ✓ |
| Enter | Enter | Run the action of the selected menu item | ✓ | ✗ |
Related articles
Related guides
Related blog articles
Configuration options
Hooks
Plugins