Adding and removing columns
Insert and remove columns programmatically with the alter() method, through the context menu, or automatically with spare columns.
Insert and remove columns with the API
Call the alter() method to change the column structure programmatically. Pass an action name, a column index, and the number of columns to insert or remove:
alter('insert_col_start', index, amount)inserts columns to the left of the given column index.alter('insert_col_end', index, amount)inserts columns to the right of the given column index.alter('remove_col', index, amount)removes columns, starting at the given column index.
In the example below, Insert column appends a column to the right of the last column, and Remove last column removes the last column.
import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';// register all Handsontable's modulesregisterAllModules();const container = document.querySelector('#example1');const insertButton = document.querySelector('#insert-column');const removeButton = document.querySelector('#remove-column');const hot = new Handsontable(container, { data: [ ['Ana García', 'Engineering', 'Senior Engineer', '2021-04-12'], ['James Okafor', 'Marketing', 'Product Manager', '2022-08-30'], ['Li Wei', 'Engineering', 'Staff Engineer', '2019-02-18'], ['Sofia Rossi', 'Sales', 'Account Executive', '2023-01-09'], ['Diego Fernández', 'Design', 'UX Designer', '2020-11-23'], ['Amara Singh', 'Engineering', 'Engineering Manager', '2018-06-05'], ], colHeaders: ['Name', 'Department', 'Title', 'Hire date'], rowHeaders: true, height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});insertButton.addEventListener('click', () => { // insert one column at the end of the grid hot.alter('insert_col_end', hot.countCols() - 1, 1);});removeButton.addEventListener('click', () => { // remove the last column, but keep at least one column in the grid if (hot.countCols() > 1) { hot.alter('remove_col', hot.countCols() - 1, 1); }});import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// register all Handsontable's modulesregisterAllModules();
const container = document.querySelector('#example1')!;const insertButton = document.querySelector('#insert-column')!;const removeButton = document.querySelector('#remove-column')!;
const hot = new Handsontable(container, { data: [ ['Ana García', 'Engineering', 'Senior Engineer', '2021-04-12'], ['James Okafor', 'Marketing', 'Product Manager', '2022-08-30'], ['Li Wei', 'Engineering', 'Staff Engineer', '2019-02-18'], ['Sofia Rossi', 'Sales', 'Account Executive', '2023-01-09'], ['Diego Fernández', 'Design', 'UX Designer', '2020-11-23'], ['Amara Singh', 'Engineering', 'Engineering Manager', '2018-06-05'], ], colHeaders: ['Name', 'Department', 'Title', 'Hire date'], rowHeaders: true, height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});
insertButton.addEventListener('click', () => { // insert one column at the end of the grid hot.alter('insert_col_end', hot.countCols() - 1, 1);});
removeButton.addEventListener('click', () => { // remove the last column, but keep at least one column in the grid if (hot.countCols() > 1) { hot.alter('remove_col', hot.countCols() - 1, 1); }});<div class="example-controls-container"> <div class="controls"> <button id="insert-column" class="button button--primary">Insert column</button> <button id="remove-column" class="button button--primary">Remove last column</button> </div></div><div id="example1"></div>The index argument uses visual column indexes. The amount argument defaults to 1 when omitted.
Add and remove columns from the context menu
Enable the contextMenu option to let users insert and remove columns by right-clicking a column. The relevant menu items are col_left (Insert column left), col_right (Insert column right), and remove_col (Remove column).
Setting contextMenu to true shows the full default menu. To show only the column actions, pass an array of item keys, as in the example below. Right-click a column header or cell to open the menu.
import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';// register all Handsontable's modulesregisterAllModules();const container = document.querySelector('#example2');new Handsontable(container, { data: [ ['Ana García', 'Engineering', 'Senior Engineer', '2021-04-12'], ['James Okafor', 'Marketing', 'Product Manager', '2022-08-30'], ['Li Wei', 'Engineering', 'Staff Engineer', '2019-02-18'], ['Sofia Rossi', 'Sales', 'Account Executive', '2023-01-09'], ['Diego Fernández', 'Design', 'UX Designer', '2020-11-23'], ['Amara Singh', 'Engineering', 'Engineering Manager', '2018-06-05'], ], colHeaders: ['Name', 'Department', 'Title', 'Hire date'], rowHeaders: true, height: 'auto', // show only the column insert and remove items in the context menu contextMenu: ['col_left', 'col_right', 'remove_col'], autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});import Handsontable from 'handsontable/base';import { registerAllModules } from 'handsontable/registry';
// register all Handsontable's modulesregisterAllModules();
const container = document.querySelector('#example2')!;
new Handsontable(container, { data: [ ['Ana García', 'Engineering', 'Senior Engineer', '2021-04-12'], ['James Okafor', 'Marketing', 'Product Manager', '2022-08-30'], ['Li Wei', 'Engineering', 'Staff Engineer', '2019-02-18'], ['Sofia Rossi', 'Sales', 'Account Executive', '2023-01-09'], ['Diego Fernández', 'Design', 'UX Designer', '2020-11-23'], ['Amara Singh', 'Engineering', 'Engineering Manager', '2018-06-05'], ], colHeaders: ['Name', 'Department', 'Title', 'Hire date'], rowHeaders: true, height: 'auto', // show only the column insert and remove items in the context menu contextMenu: ['col_left', 'col_right', 'remove_col'], autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation',});The allowInsertColumn and allowRemoveColumn options control whether these context menu items are available. Both default to true. Set allowInsertColumn to false to hide the insert items, or allowRemoveColumn to false to hide the remove item.
Add spare columns automatically
Set the minSpareCols option to keep a number of empty columns at the end of the grid. When a user enters data in the last empty column, Handsontable adds another empty column, so the grid always has at least the configured number of spare columns.
const configurationOptions = { // keep at least one empty column at the end of the grid minSpareCols: 1,};minSpareCols defaults to 0.
Control and react to column changes
Use Handsontable’s hooks to validate or respond to column changes:
beforeCreateColruns before columns are inserted. Returnfalseto cancel the insertion.afterCreateColruns after columns are inserted.beforeRemoveColruns before columns are removed. Returnfalseto cancel the removal.afterRemoveColruns after columns are removed.
For example, block removing the last remaining column:
const configurationOptions = { beforeRemoveCol(index, amount) { if (this.countCols() - amount < 1) { // cancel the removal return false; } },};Result
After completing this guide, you can insert and remove columns with the alter() method, let users add and remove columns through the context menu, keep spare columns at the end of the grid, and validate or react to column changes with hooks.
Related API reference
Configuration options
Core methods
Hooks