JavaScript Data GridContext menu

Quickly access contextual actions such as removing rows, inserting columns or copying data, by opening the context menu.

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:

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

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

To see the context menu, right-click on a cell:

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

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

This example shows how to:

  • Add common callback for all options
  • Dynamically disable option
  • Set custom text for predefined option
  • Add own custom option
  • Add callback for specific option

To see the context menu, right-click on a cell:

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

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',
    },
    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;';
        elem.textContent = 'Brought to you by...';

        return elem;
      },
      disableSelection: true,
      isCommand: false,
    },
  },
};

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,
});

Windows macOS Action Excel Sheets
Ctrl+Shift+\ or Shift+F10 Cmd+Shift+\ or Shift+F10 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

There is a newer version of Handsontable available. Switch to the latest version ⟶