docs/content/guides/getting-started/configuration-options/configuration-options.md
Configure your grid down to each column, row, and cell, using various built-in options that control Handsontable's behavior and user interface.
[[toc]]
::: only-for javascript
To apply configuration options, pass them as a second argument of the Handsontable constructor, using the object literal notation:
import Handsontable from "handsontable";
const container = document.querySelector('#example');
const hot = new Handsontable(container, {
// configuration options, in the object literal notation
licenseKey: "non-commercial-and-evaluation",
data: [
['A1', 'B1', 'C1', 'D1'],
['A2', 'B2', 'C2', 'D2'],
['A3', 'B3', 'C3', 'D3'],
],
width: 400,
height: 300,
colHeaders: true,
rowHeaders: true,
customBorders: true,
dropdownMenu: true,
multiColumnSorting: true,
filters: true,
manualRowMove: true,
});
:::
::: only-for react
To apply configuration options, pass them as individual props of the HotTable or HotColumn components.
<HotTable
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
data={[
['A1', 'B1', 'C1', 'D1'],
['A2', 'B2', 'C2', 'D2'],
['A3', 'B3', 'C3', 'D3'],
]}
width={400}
height={300}
colHeaders={true}
rowHeaders={true}
customBorders={true}
dropdownMenu={true}
multiColumnSorting={true}
filters={true}
manualRowMove={true}
/>
:::
::: only-for angular
To apply configuration options, pass them as GridSettings object to HotTableComponent.
import { GridSettings } from "@handsontable/angular-wrapper";
data = [
["A1", "B1", "C1", "D1"],
["A2", "B2", "C2", "D2"],
["A3", "B3", "C3", "D3"],
];
gridSettings: GridSettings = {
autoWrapRow: true,
autoWrapCol: true,
width: 400,
height: 300,
colHeaders: true,
rowHeaders: true,
customBorders: true,
dropdownMenu: true,
multiColumnSorting: true,
filters: true,
manualRowMove: true,
};
<hot-table [data]="data" [settings]="gridSettings" />
:::
Depending on your needs, you can apply configuration options to different elements of your grid, such as:
For the full list of available configuration options, see the configuration options' API reference.
Handsontable's configuration cascades down:
GlobalMeta)ColumnMeta)CellMeta)When you modify the mid-level column options (using the columns option):
When you modify the bottom-level cell options (using the cell option):
When you modify any options with the cells function, the changes overwrite all other options.
::: tip
The cells option is a function invoked before Handsontable's rendering cycle. Implemented incorrectly, it can slow Handsontable down. Use the cells option only if the cell option, the columns option, and the setCellMeta() method don't meet your needs.
:::
For more details on Handsontable's cascading configuration, see the MetaManager class.
Configuration options come from:
<div class="boxes-list"> </div>If you use Handsontable through modules: to use an option that comes from a Handsontable plugin, you need to import and register that plugin when initializing your Handsontable instance.
To find out if an option comes from a plugin, check the Category label in the configuration options' API reference.
::: only-for javascript
To apply configuration options to the entire grid, pass your options as a second argument of the Handsontable constructor, using the object literal notation.
:::
::: only-for react
To apply configuration options to the entire grid, pass your options as individual props of the HotTable or HotColumn components.
:::
::: only-for angular
To apply configuration options to the entire grid, pass your options as GridSettings object to HotTableComponent.
:::
For example, to set the entire grid's width and height:
::: only-for javascript
const hot = new Handsontable(container, {
// top-level grid options that apply to the entire grid
width: 400,
height: 300
});
:::
::: only-for react
<HotTable width={400} height={300} />
:::
::: only-for angular
import { GridSettings } from "@handsontable/angular-wrapper";
gridSettings: GridSettings = {
width: 400,
height: 300,
};
<hot-table [settings]="gridSettings" />
:::
To configure each cell in the grid as read-only, apply the readOnly option as a top-level grid option.
The top-level grid options cascade down:
As a result, each cell in the grid is read-only:
::: only-for javascript
::: example #example1 --js 1 --ts 2
:::
:::
::: only-for react
::: example #example1 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example1 :angular --ts 1 --html 2
:::
:::
To apply configuration options to an individual column (or a range of columns), use the columns option.
::: only-for javascript
const hot = new Handsontable(container, {
columns: [
{},
{},
// column options, apply to each cell of the third (by physical index) column
{
readOnly: true,
},
],
});
:::
::: only-for react
<HotTable
columns={[
{width: 100}, // column options for the first (by physical index) column
{width: 100}, // column options for the second (by physical index) column
{width: 100}, // column options for the third (by physical index) column
]}
/>
Alternatively, you can use the HotColumn component to configure columns declaratively:
<HotTable>
<HotColumn width={100}/>
<HotColumn width={100}/>
<HotColumn width={100}/>
</HotTable>
:::
::: only-for angular
import { GridSettings } from "@handsontable/angular-wrapper";
gridSettings: GridSettings = {
columns: [
{ width: 100 }, // column options for the first (by physical index) column
{ width: 100 }, // column options for the second (by physical index) column
{ width: 100 }, // column options for the third (by physical index) column
],
};
<hot-table [settings]="gridSettings" />
:::
In the example below, the columns option is set to a function.
The function applies the readOnly: true option to each column that has a physical index of either 2 or 8.
The modified mid-level column options:
As a result, each cell in the third and ninth columns is read-only:
::: only-for javascript
::: example #example2 --js 1 --ts 2
:::
:::
::: only-for react
::: example #example2 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example2 :angular --ts 1 --html 2
:::
:::
To apply configuration options to an individual row (or a range of rows), use the cells option.
Any options modified through cells overwrite all other options.
::: only-for javascript
The function can take three arguments:
row: a row coordinate (a physical index)col: a column coordinate (a physical index)prop: if your data is an array of objects, prop is a property name for a column's data source object.If your data is an array of arrays, prop is the same as col.
const hot = new Handsontable(container, {
// the `cells` options overwrite all other options
cells(row, col, prop) {
if (row === 1 || row === 4) {
return {
// row options, which apply to each cell of the second row
// and to each cell of the fifth row
readOnly: true,
};
}
}
});
:::
::: only-for react
The function can take three arguments:
row: a row coordinate (a physical index)
col: a column coordinate (a physical index)
prop: if your data is
an array of objects, prop is a property name for a
column's data source object.
If your data is
an array of arrays, prop is the same as col.
<HotTable cells={(row, col, prop) => {
if (row === 1 || row === 4) {
return {
// row options, which apply to each cell of the second row
// and to each cell of the fifth row
readOnly: true,
};
}
}}/>
:::
::: only-for angular
The function can take three arguments:
row: a row coordinate (a physical index)
col: a column coordinate (a physical index)
prop: if your data is
an array of objects, prop is a property name for a
column's data source object.
If your data is
an array of arrays, prop is the same as col.
import { GridSettings } from "@handsontable/angular-wrapper";
gridSettings: GridSettings = {
cells: (row, col, prop) => {
if (row === 1 || row === 4) {
return {
// row options, which apply to each cell of the second row
// and to each cell of the fifth row
readOnly: true,
};
}
},
};
<hot-table [settings]="gridSettings" />
:::
In the example below, the cells option sets each cell in the first and fourth row as readOnly.
Options modified through cells overwrite all other options.
::: only-for javascript
::: example #example3 --js 1 --ts 2
:::
:::
::: only-for react
::: example #example3 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example3 :angular --ts 1 --html 2
:::
:::
To apply configuration options to individual cells, use the cell option.
::: only-for javascript
const hot = new Handsontable(container, {
cell: [
{
// cell options, apply only to a cell with coordinates (0, 0)
row: 0,
col: 0,
readOnly: true,
},
{
// cell options, apply only to a cell with coordinates (1, 1)
row: 1,
col: 1,
readOnly: true,
}
],
autoWrapRow: true,
autoWrapCol: true,
});
:::
::: only-for react
<HotTable cell={[
{ // bottom-level cell options overwrite the top-level grid options
// apply only to a cell with coordinates (0, 0)
row: 0,
col: 0,
},
{
// bottom-level cell options overwrite the top-level grid options
// apply only to a cell with coordinates (1, 1)
row: 1,
col: 1,
}
]}/>
:::
::: only-for angular
import { GridSettings } from "@handsontable/angular-wrapper";
gridSettings: GridSettings = {
cell: [
{
// bottom-level cell options overwrite the top-level grid options
// apply only to a cell with coordinates (0, 0)
row: 0,
col: 0,
},
{
// bottom-level cell options overwrite the top-level grid options
// apply only to a cell with coordinates (1, 1)
row: 1,
col: 1,
},
],
};
<hot-table [settings]="gridSettings" />
:::
In the example below, the cell option sets cell A1(0, 0) and cell B2(1, 1) as readOnly.
The modified cell options:
::: only-for javascript
::: example #example4 --js 1 --ts 2
:::
:::
::: only-for react
::: example #example4 :react --js 1 --ts 2
:::
:::
::: only-for angular
::: example #example4 :angular --ts 1 --html 2
:::
:::
When Handsontable is running, you can check a cell's current options, using the getCellMeta() method.
The getCellMeta() method returns an object with:
For example:
::: only-for javascript
import Handsontable from 'handsontable';
const container = document.querySelector('#example');
const hot = new Handsontable(container, {
// top-level grid options that apply to the entire grid
data: [
['A1', 'B1', 'C1', 'D1'],
['A2', 'B2', 'C2', 'D2'],
['A3', 'B3', 'C3', 'D3'],
],
licenseKey: 'non-commercial-and-evaluation',
width: 'auto',
height: 'auto',
rowHeaders: true,
colHeaders: true,
// in the top-level grid options, all cells are read-only
readOnly: false,
cell: [
{
// bottom-level cell options overwrite the top-level grid options
// apply only to a cell with coordinates (1, 1)
row: 1,
col: 1,
readOnly: true,
}
]
});
// for cell (0, 0), the `readOnly` option is the default (`false`)
// returns `false`
hot.getCellMeta(0, 0).readOnly;
// for cell (1, 1), the `cell` option overwrote the default `readOnly` value
// returns `true`
hot.getCellMeta(1, 1).readOnly;
:::
::: only-for react
// Consider the HotTable component with the `cell` option declared:
<HotTable
cell={[
{
row: 1,
col: 1,
readOnly: true,
}
]}
/>;
// for cell (0, 0), the `readOnly` option is the default (`false`)
// returns `false`
hot.getCellMeta(0, 0).readOnly;
// for cell (1, 1), the `cell` option overwrote the default `readOnly` value
// returns `true`
hot.getCellMeta(1, 1).readOnly;
:::
::: only-for angular
@ViewChild(HotTableComponent, { static: false }) readonly hotTable!: HotTableComponent;
import { GridSettings } from "@handsontable/angular-wrapper";
// Consider the HotTable component with the `cell` option declared:
gridSettings: GridSettings = {
cell: [
{
row: 1,
col: 1,
readOnly: true,
},
]
};
// for cell (0, 0), the `readOnly` option is the default (`false`)
// returns `false`
hotTable.hotInstance.getCellMeta(0, 0).readOnly;
// for cell (1, 1), the `cell` option overwrote the default `readOnly` value
// returns `true`
hotTable.hotInstance.getCellMeta(1, 1).readOnly;
<hot-table [settings]="gridSettings" />
:::
When Handsontable is running, you can change the initial cell options, using the setCellMeta() method.
For example:
::: only-for javascript
import Handsontable from 'handsontable';
const container = document.querySelector('#example');
const hot = new Handsontable(container, {
// top-level grid options that apply to the entire grid
data: [
['A1', 'B1', 'C1', 'D1'],
['A2', 'B2', 'C2', 'D2'],
['A3', 'B3', 'C3', 'D3'],
],
licenseKey: 'non-commercial-and-evaluation',
width: 'auto',
height: 'auto',
rowHeaders: true,
colHeaders: true,
});
// changes the `readOnly` option of cell (1, 1) back to `false`
hot.setCellMeta(1, 1, 'readOnly', false);
// returns `false`
hot.getCellMeta(1, 1).readOnly;
:::
::: only-for react
// changes the `readOnly` option of cell (1, 1) back to `false`
hot.setCellMeta(1, 1, 'readOnly', false);
// returns `false`
hot.getCellMeta(1, 1).readOnly;
:::
::: only-for angular
@ViewChild(HotTableComponent, { static: false }) readonly hotTable!: HotTableComponent;
import { GridSettings } from "@handsontable/angular-wrapper";
// Consider the HotTable component with the `cell` option declared:
gridSettings: GridSettings = {
cell: [
{
row: 1,
col: 1,
readOnly: true,
},
]
};
// changes the `readOnly` option of cell (1, 1) back to `false`
hotTable.hotInstance.setCellMeta(1, 1, "readOnly", false);
// returns `false`
hotTable.hotInstance.getCellMeta(1, 1).readOnly;
<hot-table [settings]="gridSettings" />
:::
You can apply configuration options to individual grid elements (columns, rows, cells), based on any logic you implement, using the cells option.
The cells option overwrites all other options.
::: only-for javascript
The function can take three arguments:
row: a row coordinate (a physical index)col: a column coordinate (a physical index)prop: if your data is an array of objects, prop is a property name for a column's data source object.If your data is an array of arrays, prop is the same as col.
const hot = new Handsontable(container, {
cells(row, col) {
if ((row === 1 || row === 5) && col === 1) {
return {
readOnly: true,
};
}
}
});
:::
::: only-for react
The function can take three arguments:
row: a row coordinate (a physical index)
col: a column coordinate (a physical index)
prop: if your data is
an array of objects, prop is a property name for a
column's data source object.
If your data is
an array of arrays, prop is the same as col.
<HotTable
cells={(row, col) => {
if ((row === 1 || row === 5) && col === 1) {
return {
readOnly: true,
};
}
}}
/>
:::
::: only-for angular
The function can take three arguments:
row: a row coordinate (a physical index)
col: a column coordinate (a physical index)
prop: if your data is
an array of objects, prop is a property name for a
column's data source object.
If your data is
an array of arrays, prop is the same as col.
import { GridSettings } from "@handsontable/angular-wrapper";
gridSettings: GridSettings = {
cells: (row, col) => {
if ((row === 1 || row === 5) && col === 1) {
return {
readOnly: true,
};
}
},
};
<hot-table [settings]="gridSettings" />
:::
In the example below, the modified cells options overwrite the top-level grid options.
::: only-for javascript
::: example #example5 --js 1 --ts 2
:::
:::
::: only-for react
// for cell (0, 0), the `readOnly` option is the default (`false`)
// returns `false`
hot.getCellMeta(0, 0).readOnly;
// for cell (1, 1), the `cell` option overwrote the default `readOnly` value
// returns `true`
hot.getCellMeta(1, 1).readOnly;
// changes the `readOnly` option of cell (1, 1) back to `false`
hot.setCellMeta(1, 1, 'readOnly', false);
// returns `false`
hot.getCellMeta(1, 1).readOnly;
:::
::: only-for angular
// for cell (0, 0), the `readOnly` option is the default (`false`)
// returns `false`
hot.getCellMeta(0, 0).readOnly;
// for cell (1, 1), the `cell` option overwrote the default `readOnly` value
// returns `true`
hot.getCellMeta(1, 1).readOnly;
// changes the `readOnly` option of cell (1, 1) back to `false`
hot.setCellMeta(1, 1, 'readOnly', false);
// returns `false`
hot.getCellMeta(1, 1).readOnly;
:::
In the example below, some cells are read-only, and some cells are editable:
By default, all cells are read-only (as set in the top-level grid options).
For the first column, the mid-level column options overwrite the top-level grid options.
As a result, the first column cells are editable.
For cell A1 (0, 0), the bottom-level cell options overwrite both the mid-level column options, and the top-level grid options.
As a result, cell A1 (0, 0) is read-only, despite being part of the editable first column.
For cell C3 (3, 3), the cells option overwrites all other options.
As a result, cell C3 (3, 3) is editable, despite not being part of the editable first column.
::: only-for javascript
::: example #example6 --js 1 --ts 2
:::
:::
::: only-for react
::: example #example6 :react --js 1 --ts 2
:::
:::
::: only-for react
A non-idempotent option is one that produces different results when applied multiple times. In the context of Handsontable and <HotTable/> component, options like manualColumnMove=[1, 0] will swap columns every time they're applied - first application swaps columns, second application swaps them back, third swaps again, and so on.
Non-idempotent options like manualColumnMove and manualRowMove cause unwanted visual changes on every React re-render because they operate on visual indexes.
// Problem: Columns swap on EVERY re-render
const ExampleComponent = () => {
const [state, setState] = React.useState(0);
return (
<>
<button onClick={() => setState(state + 1)}>{state}</button>
<HotTable
manualColumnMove={[1, 0]} // Columns keep swapping!
data={[['A', 'B'], [0, 1]]}
licenseKey="non-commercial-and-evaluation"
/>
</>
);
};
Use initialState to apply these options only during initialization:
<HotTable
initialState={{
manualColumnMove: [1, 0] // Applied only once
}}
data={[['A', 'B'], [0, 1]]}
rowHeaders={true}
colHeaders={true}
licenseKey="non-commercial-and-evaluation"
/>
:::
::: only-for angular
::: example #example6 :angular --ts 1 --html 2
:::
:::
Configuration options
<div class="boxes-list"> </div>Core methods
<div class="boxes-list">Hooks
<div class="boxes-list"> </div>Your grid now applies configuration options at the scope you specified -- grid-wide, per column, per row, or per individual cell -- using Handsontable's cascading configuration system.