Skip to content

Make specified cells read-only to protect them from unwanted changes but still allow navigation and copying of data.

Overview

Disabling a cell makes the cell read-only or non-editable. Both have similar outcomes, with the following differences:

Read-only cell
readOnly: true
Non-editable cell
editor: false
Has an additional CSS class (htDimmed)Has no additional CSS class
Copy works, paste doesn’t workCopy-paste works
Drag-to-fill doesn’t workDrag-to-fill works
Can’t be changed by populateFromArray()Can be changed by populateFromArray()

Read-only grid

You can make the entire grid read-only by setting readOnly to true as a top-level grid option.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#exampleReadOnlyGrid');
new Handsontable(container, {
data: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
height: 'auto',
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
licenseKey: 'non-commercial-and-evaluation',
// make the entire grid read-only
readOnly: true,
autoWrapRow: true,
autoWrapCol: true,
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#exampleReadOnlyGrid')!;
new Handsontable(container, {
data: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
height: 'auto',
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
licenseKey: 'non-commercial-and-evaluation',
// make the entire grid read-only
readOnly: true,
autoWrapRow: true,
autoWrapCol: true,
});

Read-only columns

In many use cases, you will need to configure a certain column to be read-only. This column will be available for keyboard navigation and copying data (Ctrl/Cmd+C). Editing and pasting data will be disabled.

To make a column read-only, declare it in the columns configuration option. You can also define a special renderer function that will dim the read-only values, providing a visual cue for the user that the cells are read-only.

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: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
height: 'auto',
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
licenseKey: 'non-commercial-and-evaluation',
columns: [
{
data: 'car',
readOnly: true,
},
{
data: 'year',
},
{
data: 'chassis',
},
{
data: 'bumper',
},
],
autoWrapRow: true,
autoWrapCol: true,
});
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: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
height: 'auto',
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
licenseKey: 'non-commercial-and-evaluation',
columns: [
{
data: 'car',
readOnly: true,
},
{
data: 'year',
},
{
data: 'chassis',
},
{
data: 'bumper',
},
],
autoWrapRow: true,
autoWrapCol: true,
});

Read-only specific cells

This example makes cells that contain the word “Nissan” read-only. It forces all cells to be processed by the cells function which will decide whether a cell’s metadata should have the readOnly property set.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example2');
const hot = new Handsontable(container, {
data: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
hot.updateSettings({
cells(row, col) {
return hot.getData()[row][col] === 'Nissan' ? { readOnly: true } : {};
},
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example2')!;
const hot = new Handsontable(container, {
data: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
hot.updateSettings({
cells(row, col) {
return hot.getData()[row][col] === 'Nissan' ? { readOnly: true } : {};
},
});

Non-editable cells behave like any other cells apart from preventing you from manually changing their values.

Non-editable columns

In many cases, you will need to configure a certain column to be non-editable. Doing this does not change its basic behaviour, apart from editing. This means that you can still use the keyboard navigation Ctrl/Cmd+C, and Ctrl/Cmd+V functionalities, and drag-to-fill, etc.

To make a column non-editable, declare it in the columns configuration option. You can also define a special renderer function that will dim the editor value. This will provide the user with a visual cue that the cell is non-editable.

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: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
height: 'auto',
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
licenseKey: 'non-commercial-and-evaluation',
columns: [
{
data: 'car',
editor: false,
},
{
data: 'year',
editor: 'numeric',
},
{
data: 'chassis',
editor: 'text',
},
{
data: 'bumper',
editor: 'text',
},
],
autoWrapRow: true,
autoWrapCol: true,
});
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: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
height: 'auto',
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
licenseKey: 'non-commercial-and-evaluation',
columns: [
{
data: 'car',
editor: false,
},
{
data: 'year',
editor: 'numeric',
},
{
data: 'chassis',
editor: 'text',
},
{
data: 'bumper',
editor: 'text',
},
],
autoWrapRow: true,
autoWrapCol: true,
});

Non-editable specific cells

The following example shows the table with non-editable cells containing the word “Nissan”. This cell property is optional and you can easily set it in the Handsontable configuration.

JavaScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example4');
const hot = new Handsontable(container, {
data: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
hot.updateSettings({
cells(row, _col, prop) {
return hot.getDataAtRowProp(row, prop) === 'Nissan' ? { editor: false } : { editor: 'text' };
},
});
TypeScript
import Handsontable from 'handsontable/base';
import { registerAllModules } from 'handsontable/registry';
// Register all Handsontable's modules.
registerAllModules();
const container = document.querySelector('#example4')!;
const hot = new Handsontable(container, {
data: [
{ car: 'Tesla', year: 2017, chassis: 'black', bumper: 'black' },
{ car: 'Nissan', year: 2018, chassis: 'blue', bumper: 'blue' },
{ car: 'Chrysler', year: 2019, chassis: 'yellow', bumper: 'black' },
{ car: 'Volvo', year: 2020, chassis: 'white', bumper: 'gray' },
],
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
height: 'auto',
autoWrapRow: true,
autoWrapCol: true,
licenseKey: 'non-commercial-and-evaluation',
});
hot.updateSettings({
cells(row, _col, prop) {
return hot.getDataAtRowProp(row, prop as string) === 'Nissan' ? { editor: false } : { editor: 'text' };
},
});

Configuration options