Skip to content

Add a comment (a note) to a cell, using the context menu, just like in Excel. Edit and delete comments. Make comments read-only.

Enable the plugin

Set the comments configuration option to true to enable the feature and add all the needed context menu items. For example:

const hot = new Handsontable(container, {
data: [
['A1', 'B1', 'C1'],
['A2', 'B2', 'C2'],
],
comments: true,
autoWrapRow: true,
autoWrapCol: true
});

Add comments via the context menu

After you’ve enabled the plugin, the Context Menu gains a few new items:

  • Add/Edit comment
  • Delete comment
  • Read-only comment

Set up pre-set comments

You can also pre-define comments for your table. Comments are stored in the table’s/column’s/cell’s metadata object and you can declare as any value of the respective type. For example:

cell: [
{ row: 1, col: 1, comment: { value: 'Hello world!' } }
]

In this example, the comment “Hello world!” is added to the cell at (1,1).

Basic example

JavaScript
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,
comments: true,
cell: [
{ row: 1, col: 1, comment: { value: 'Some comment' } },
{ row: 2, col: 2, comment: { value: 'More comments' } },
],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
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,
comments: true,
cell: [
{ row: 1, col: 1, comment: { value: 'Some comment' } },
{ row: 2, col: 2, comment: { value: 'More comments' } },
],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Make a comment read-only

By default, all comments are editable. To change this, set the readOnly configuration option to true when adding a comment. This example makes the “Tesla” comment attached to a cell read-only, whereas the “Honda” comment attached to another cell is editable.

JavaScript
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', 'Toyota', 'Honda', 'Ford'],
['2018', 10, 11, 12, 13, 15, 16],
['2019', 10, 11, 12, 13, 15, 16],
['2020', 10, 11, 12, 13, 15, 16],
],
rowHeaders: true,
colHeaders: true,
contextMenu: true,
comments: true,
cell: [
{
row: 0,
col: 1,
comment: { value: 'A read-only comment.', readOnly: true },
},
{ row: 0, col: 3, comment: { value: 'You can edit this comment' } },
],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
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', 'Toyota', 'Honda', 'Ford'],
['2018', 10, 11, 12, 13, 15, 16],
['2019', 10, 11, 12, 13, 15, 16],
['2020', 10, 11, 12, 13, 15, 16],
],
rowHeaders: true,
colHeaders: true,
contextMenu: true,
comments: true,
cell: [
{
row: 0,
col: 1,
comment: { value: 'A read-only comment.', readOnly: true },
},
{ row: 0, col: 3, comment: { value: 'You can edit this comment' } },
],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Set a comment box’s size

To set the width and height of a comment box, use the style parameter.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
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],
],
rowHeaders: true,
colHeaders: true,
contextMenu: true,
comments: true,
cell: [
{ row: 1, col: 1, comment: { value: 'Some comment' } },
// add the `style` parameter
{
row: 2,
col: 2,
comment: {
value: 'Comment 200x50 px',
style: { width: 200, height: 50 },
},
},
],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
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],
],
rowHeaders: true,
colHeaders: true,
contextMenu: true,
comments: true,
cell: [
{ row: 1, col: 1, comment: { value: 'Some comment' } },
// add the `style` parameter
{
row: 2,
col: 2,
comment: {
value: 'Comment 200x50 px',
style: { width: 200, height: 50 },
},
},
],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});

Set a delay for displaying comments

To display comments after a pre-configured time delay, use the displayDelay parameter.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example4');
new Handsontable(container, {
data: [
['', 'Tesla', 'Toyota', 'Honda', 'Ford'],
['2018', 10, 11, 12, 13, 15, 16],
['2019', 10, 11, 12, 13, 15, 16],
['2020', 10, 11, 12, 13, 15, 16],
],
rowHeaders: true,
colHeaders: true,
contextMenu: true,
comments: {
// on mouseover, wait 2 seconds before the comment box displays
displayDelay: 2000,
},
cell: [{ row: 1, col: 1, comment: { value: 'Some comment' } }],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example4')!;
new Handsontable(container, {
data: [
['', 'Tesla', 'Toyota', 'Honda', 'Ford'],
['2018', 10, 11, 12, 13, 15, 16],
['2019', 10, 11, 12, 13, 15, 16],
['2020', 10, 11, 12, 13, 15, 16],
],
rowHeaders: true,
colHeaders: true,
contextMenu: true,
comments: {
// on mouseover, wait 2 seconds before the comment box displays
displayDelay: 2000,
},
cell: [{ row: 1, col: 1, comment: { value: 'Some comment' } }],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
WindowsmacOSActionExcelSheets
Ctrl+Alt+MCtrl+Option+MAdd or edit a comment
Ctrl+EnterCmd+EnterSave and exit the current comment
EscapeEscapeExit the current comment without saving

Configuration options