Skip to content

Dropdown cell type

Collect user input with a searchable list of choices, by using the dropdown cell type.

The dropdown cell type lets users select a value from a predefined list. It is a simplified version of autocomplete with strict mode always on.

Overview

The dropdown cell type is based on an autocomplete cell type and can also be searchable.

Usage

This example shows the usage of the dropdown feature. Dropdown is based on Autocomplete cell type. All options used by autocomplete cell type apply to dropdown as well.

Internally, cell type="dropdown" is equivalent to cell type="autocomplete" strict={true} filter={false}. Therefore you can think of dropdown as a searchable <select>. Strict mode cannot be turned off here: a dropdown cell ignores strict={false}. See Validate dropdown values.

JavaScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = () => {
return (
<HotTable
height="auto"
data={[
['Tesla', 2017, 'black', 'black'],
['Nissan', 2018, 'blue', 'blue'],
['Chrysler', 2019, 'yellow', 'black'],
['Volvo', 2020, 'white', 'gray'],
]}
colHeaders={['Car', 'Year', 'Chassis color', 'Bumper color']}
columns={[
{},
{ type: 'numeric' },
{
type: 'dropdown',
source: ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white'],
},
{
type: 'dropdown',
source: ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white'],
},
]}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;
TypeScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = () => {
return (
<HotTable
height="auto"
data={[
['Tesla', 2017, 'black', 'black'],
['Nissan', 2018, 'blue', 'blue'],
['Chrysler', 2019, 'yellow', 'black'],
['Volvo', 2020, 'white', 'gray'],
]}
colHeaders={['Car', 'Year', 'Chassis color', 'Bumper color']}
columns={[
{},
{ type: 'numeric' },
{
type: 'dropdown',
source: ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white'],
},
{
type: 'dropdown',
source: ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white'],
},
]}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;

The source option

The source option can be provided in two formats:

You can also assign a function to load the options from a remote source, as described in Autocomplete strict mode with asynchronous data. Handsontable ignores a response that arrives after the editor closed - including a close you may not notice, such as scrolling the edited cell out of view - and it ignores a response that a newer query has superseded, which happens as you type. Call the callback whenever the request completes, even late.

Array of values

You can provide the source option as an array of values that will be used as the dropdown options.

JavaScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = () => {
const shipmentKVData = [
['Electronics and Gadgets', 'Los Angeles International Airport'],
['Medical Supplies', 'John F. Kennedy International Airport'],
['Auto Parts', "Chicago O'Hare International Airport"],
['Fresh Produce', 'London Heathrow Airport'],
['Textiles', 'Charles de Gaulle Airport'],
['Industrial Equipment', 'Dubai International Airport'],
['Pharmaceuticals', 'Tokyo Haneda Airport'],
['Consumer Goods', 'Beijing Capital International Airport'],
['Machine Parts', 'Singapore Changi Airport'],
['Food Products', 'Amsterdam Airport Schiphol'],
];
const airportKVData = [
'Los Angeles International Airport',
'John F. Kennedy International Airport',
"Chicago O'Hare International Airport",
'London Heathrow Airport',
'Charles de Gaulle Airport',
'Dubai International Airport',
'Tokyo Haneda Airport',
'Beijing Capital International Airport',
'Singapore Changi Airport',
'Amsterdam Airport Schiphol',
'Frankfurt Airport',
'Seoul Incheon International Airport',
'Toronto Pearson International Airport',
'Madrid-Barajas Airport',
'Bangkok Suvarnabhumi Airport',
'Munich International Airport',
'Sydney Kingsford Smith Airport',
'Barcelona-El Prat Airport',
'Kuala Lumpur International Airport',
'Zurich Airport',
];
return (
<HotTable
height="auto"
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
data={shipmentKVData}
columns={[
{
title: 'Shipment',
},
{
type: 'dropdown',
source: airportKVData,
title: 'Airport',
},
]}
/>
);
};
export default ExampleComponent;
TypeScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = () => {
const shipmentKVData = [
['Electronics and Gadgets', 'Los Angeles International Airport'],
['Medical Supplies', 'John F. Kennedy International Airport'],
['Auto Parts', "Chicago O'Hare International Airport"],
['Fresh Produce', 'London Heathrow Airport'],
['Textiles', 'Charles de Gaulle Airport'],
['Industrial Equipment', 'Dubai International Airport'],
['Pharmaceuticals', 'Tokyo Haneda Airport'],
['Consumer Goods', 'Beijing Capital International Airport'],
['Machine Parts', 'Singapore Changi Airport'],
['Food Products', 'Amsterdam Airport Schiphol'],
];
const airportKVData = [
'Los Angeles International Airport',
'John F. Kennedy International Airport',
"Chicago O'Hare International Airport",
'London Heathrow Airport',
'Charles de Gaulle Airport',
'Dubai International Airport',
'Tokyo Haneda Airport',
'Beijing Capital International Airport',
'Singapore Changi Airport',
'Amsterdam Airport Schiphol',
'Frankfurt Airport',
'Seoul Incheon International Airport',
'Toronto Pearson International Airport',
'Madrid-Barajas Airport',
'Bangkok Suvarnabhumi Airport',
'Munich International Airport',
'Sydney Kingsford Smith Airport',
'Barcelona-El Prat Airport',
'Kuala Lumpur International Airport',
'Zurich Airport',
];
return (
<HotTable
height="auto"
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
data={shipmentKVData}
columns={[
{
title: 'Shipment',
},
{
type: 'dropdown',
source: airportKVData,
title: 'Airport',
},
]}
/>
);
};
export default ExampleComponent;

Array of objects

You can provide the source option as an array of objects with key and value properties. The value property will be used as the dropdown option, while the entire object will be used as the value of the cell.

JavaScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = () => {
const shipmentKVData = [
['Electronics and Gadgets', { key: 'LAX', value: 'Los Angeles International Airport' }],
['Medical Supplies', { key: 'JFK', value: 'John F. Kennedy International Airport' }],
['Auto Parts', { key: 'ORD', value: "Chicago O'Hare International Airport" }],
['Fresh Produce', { key: 'LHR', value: 'London Heathrow Airport' }],
['Textiles', { key: 'CDG', value: 'Charles de Gaulle Airport' }],
['Industrial Equipment', { key: 'DXB', value: 'Dubai International Airport' }],
['Pharmaceuticals', { key: 'HND', value: 'Tokyo Haneda Airport' }],
['Consumer Goods', { key: 'PEK', value: 'Beijing Capital International Airport' }],
['Machine Parts', { key: 'SIN', value: 'Singapore Changi Airport' }],
['Food Products', { key: 'AMS', value: 'Amsterdam Airport Schiphol' }],
];
const airportKVData = [
{ key: 'LAX', value: 'Los Angeles International Airport' },
{ key: 'JFK', value: 'John F. Kennedy International Airport' },
{ key: 'ORD', value: "Chicago O'Hare International Airport" },
{ key: 'LHR', value: 'London Heathrow Airport' },
{ key: 'CDG', value: 'Charles de Gaulle Airport' },
{ key: 'DXB', value: 'Dubai International Airport' },
{ key: 'HND', value: 'Tokyo Haneda Airport' },
{ key: 'PEK', value: 'Beijing Capital International Airport' },
{ key: 'SIN', value: 'Singapore Changi Airport' },
{ key: 'AMS', value: 'Amsterdam Airport Schiphol' },
{ key: 'FRA', value: 'Frankfurt Airport' },
{ key: 'ICN', value: 'Seoul Incheon International Airport' },
{ key: 'YYZ', value: 'Toronto Pearson International Airport' },
{ key: 'MAD', value: 'Madrid-Barajas Airport' },
{ key: 'BKK', value: 'Bangkok Suvarnabhumi Airport' },
{ key: 'MUC', value: 'Munich International Airport' },
{ key: 'SYD', value: 'Sydney Kingsford Smith Airport' },
{ key: 'BCN', value: 'Barcelona-El Prat Airport' },
{ key: 'KUL', value: 'Kuala Lumpur International Airport' },
{ key: 'ZRH', value: 'Zurich Airport' },
];
return (
<HotTable
height="auto"
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
data={shipmentKVData}
columns={[
{
title: 'Shipment',
},
{
type: 'dropdown',
source: airportKVData,
title: 'Airport',
},
]}
/>
);
};
export default ExampleComponent;
TypeScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const ExampleComponent = () => {
const shipmentKVData = [
['Electronics and Gadgets', { key: 'LAX', value: 'Los Angeles International Airport' }],
['Medical Supplies', { key: 'JFK', value: 'John F. Kennedy International Airport' }],
['Auto Parts', { key: 'ORD', value: "Chicago O'Hare International Airport" }],
['Fresh Produce', { key: 'LHR', value: 'London Heathrow Airport' }],
['Textiles', { key: 'CDG', value: 'Charles de Gaulle Airport' }],
['Industrial Equipment', { key: 'DXB', value: 'Dubai International Airport' }],
['Pharmaceuticals', { key: 'HND', value: 'Tokyo Haneda Airport' }],
['Consumer Goods', { key: 'PEK', value: 'Beijing Capital International Airport' }],
['Machine Parts', { key: 'SIN', value: 'Singapore Changi Airport' }],
['Food Products', { key: 'AMS', value: 'Amsterdam Airport Schiphol' }],
];
const airportKVData = [
{ key: 'LAX', value: 'Los Angeles International Airport' },
{ key: 'JFK', value: 'John F. Kennedy International Airport' },
{ key: 'ORD', value: "Chicago O'Hare International Airport" },
{ key: 'LHR', value: 'London Heathrow Airport' },
{ key: 'CDG', value: 'Charles de Gaulle Airport' },
{ key: 'DXB', value: 'Dubai International Airport' },
{ key: 'HND', value: 'Tokyo Haneda Airport' },
{ key: 'PEK', value: 'Beijing Capital International Airport' },
{ key: 'SIN', value: 'Singapore Changi Airport' },
{ key: 'AMS', value: 'Amsterdam Airport Schiphol' },
{ key: 'FRA', value: 'Frankfurt Airport' },
{ key: 'ICN', value: 'Seoul Incheon International Airport' },
{ key: 'YYZ', value: 'Toronto Pearson International Airport' },
{ key: 'MAD', value: 'Madrid-Barajas Airport' },
{ key: 'BKK', value: 'Bangkok Suvarnabhumi Airport' },
{ key: 'MUC', value: 'Munich International Airport' },
{ key: 'SYD', value: 'Sydney Kingsford Smith Airport' },
{ key: 'BCN', value: 'Barcelona-El Prat Airport' },
{ key: 'KUL', value: 'Kuala Lumpur International Airport' },
{ key: 'ZRH', value: 'Zurich Airport' },
];
return (
<HotTable
height="auto"
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
data={shipmentKVData}
columns={[
{
title: 'Shipment',
},
{
type: 'dropdown',
source: airportKVData,
title: 'Airport',
},
]}
/>
);
};
export default ExampleComponent;

API methods

When working with object-based dropdown data, you can use methods like getSourceData(), getSourceDataAtCell(), getSourceDataAtRow() etc., to get the data in its original object format with both key and value properties. The getData() method will return only the value property’s content.

Writing a plain value

You don’t have to build the object yourself. When you write a plain value into the cell, Handsontable looks it up among the value properties of the source array. On a match, the cell stores the whole matching object, with its key.

This applies to every way a value reaches the cell:

  • picking an option in the editor
  • typing an option’s text and pressing Enter
  • pasting text, including a paste from another application and a paste as plain text (Ctrl/Cmd + Shift + V)
  • calling setDataAtCell() or populateFromArray()

A value that matches no option is stored as you wrote it. The dropdown cell type is strict, so such a value fails validation and the cell is marked as invalid.

The lookup compares the text the cell displays, so a numeric value matches its string form. It’s skipped when source is a function, because the options aren’t known until the function answers.

Set the dropdown width

By default, the dropdown list matches the width of the edited cell, so long options can be truncated. To let the list expand to fit its longest option, set trimDropdown to false.

SettingDescription
true (default)Match the dropdown list’s width to the edited cell.
falseExpand the list to its content, but keep it at least as wide as the edited cell.

In the example below, the Department (default) column trims the list to the cell, while the Department (full width) column expands it. Open a cell in each column to compare.

JavaScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const departments = [
'Engineering and Platform Infrastructure',
'Marketing and Brand Communications',
'Financial Planning and Analysis',
'People Operations and Talent Acquisition',
'Customer Success and Enterprise Accounts',
];
const ExampleComponent = () => {
return (
<HotTable
height="auto"
data={[
['Ana García', departments[0], departments[0]],
['James Okafor', departments[1], departments[1]],
['Li Wei', departments[2], departments[2]],
['Sofia Rossi', departments[3], departments[3]],
]}
colHeaders={['Employee', 'Department (default)', 'Department (full width)']}
columns={[
{},
{
type: 'dropdown',
source: departments,
width: 140,
// trim the list to the cell's width (default)
trimDropdown: true,
},
{
type: 'dropdown',
source: departments,
width: 140,
// expand the list to fit its longest option
trimDropdown: false,
},
]}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;
TypeScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const departments = [
'Engineering and Platform Infrastructure',
'Marketing and Brand Communications',
'Financial Planning and Analysis',
'People Operations and Talent Acquisition',
'Customer Success and Enterprise Accounts',
];
const ExampleComponent = () => {
return (
<HotTable
height="auto"
data={[
['Ana García', departments[0], departments[0]],
['James Okafor', departments[1], departments[1]],
['Li Wei', departments[2], departments[2]],
['Sofia Rossi', departments[3], departments[3]],
]}
colHeaders={['Employee', 'Department (default)', 'Department (full width)']}
columns={[
{},
{
type: 'dropdown',
source: departments,
width: 140,
// trim the list to the cell's width (default)
trimDropdown: true,
},
{
type: 'dropdown',
source: departments,
width: 140,
// expand the list to fit its longest option
trimDropdown: false,
},
]}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;

Set the dropdown height

By default, the dropdown list shows up to 10 options before a scrollbar appears. To change how many options are visible at once, set visibleRows to the number of options you want to show.

In the example below, the Job title (default) column uses the default height, while the Job title (compact) column shows three options at a time. Open a cell in each column to compare.

JavaScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const jobTitles = [
'Software Engineer',
'Senior Software Engineer',
'Staff Engineer',
'Engineering Manager',
'Product Manager',
'Product Designer',
'Data Analyst',
'Data Scientist',
'Marketing Specialist',
'Account Executive',
'Customer Success Manager',
'Finance Analyst',
'Recruiter',
'Office Manager',
];
const ExampleComponent = () => {
return (
<HotTable
height="auto"
data={[
['Ana García', 'Senior Software Engineer', 'Senior Software Engineer'],
['James Okafor', 'Product Manager', 'Product Manager'],
['Li Wei', 'Data Scientist', 'Data Scientist'],
['Sofia Rossi', 'Account Executive', 'Account Executive'],
]}
colHeaders={['Employee', 'Job title (default)', 'Job title (compact)']}
columns={[
{},
{
type: 'dropdown',
source: jobTitles,
},
{
type: 'dropdown',
source: jobTitles,
// show 3 options at a time, then scroll
visibleRows: 3,
},
]}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;
TypeScript
import { HotTable } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modules
registerAllModules();
const jobTitles = [
'Software Engineer',
'Senior Software Engineer',
'Staff Engineer',
'Engineering Manager',
'Product Manager',
'Product Designer',
'Data Analyst',
'Data Scientist',
'Marketing Specialist',
'Account Executive',
'Customer Success Manager',
'Finance Analyst',
'Recruiter',
'Office Manager',
];
const ExampleComponent = () => {
return (
<HotTable
height="auto"
data={[
['Ana García', 'Senior Software Engineer', 'Senior Software Engineer'],
['James Okafor', 'Product Manager', 'Product Manager'],
['Li Wei', 'Data Scientist', 'Data Scientist'],
['Sofia Rossi', 'Account Executive', 'Account Executive'],
]}
colHeaders={['Employee', 'Job title (default)', 'Job title (compact)']}
columns={[
{},
{
type: 'dropdown',
source: jobTitles,
},
{
type: 'dropdown',
source: jobTitles,
// show 3 options at a time, then scroll
visibleRows: 3,
},
]}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
/>
);
};
export default ExampleComponent;

Validate dropdown values

The dropdown validator always runs in strict mode. A value that is not in the source list is marked invalid, whether it is typed, pasted, or set with setDataAtCell(). The strict option has no effect on dropdown cells.

The allowInvalid option decides what happens to an invalid value, the same as in Autocomplete strict mode.

Validation runs when a value is written to a cell. Values that are already in the data source when the grid loads are not validated. To check and mark them, call validateCells() after the grid is created.

Result

After configuring the dropdown cell type, cells display a button that opens a dropdown list of options. Users can search the list by typing. Only values from the source list are accepted. The selected value is stored in the data source.

Keyboard shortcuts

The dropdown cell editor is an autocomplete editor with strict mode always on, so it uses the same keyboard shortcuts as Autocomplete strict mode. See the keyboard shortcuts reference for details.

Related guides

Configuration options

Core methods

Hooks