Skip to content

Display empty data state overlays and provide user feedback when your data grid has no data to display using the Empty Data State plugin.

Overview

The Empty Data State plugin provides a user-friendly overlay system for Handsontable when there’s no data to display. It automatically detects when your table is empty or when all data is hidden by filters, and displays an appropriate message with optional action buttons.

With simplicity and effectiveness in mind, the empty data state plugin was designed to provide a consistent user experience with customizable appearance and behavior. It automatically integrates with the Filters plugin to provide context-aware messages and actions.

Basic configuration

To enable the Empty Data State plugin, set the emptyDataState option to true or provide a configuration object.

JavaScript
import Handsontable from 'handsontable';
const container = document.getElementById('example1');
new Handsontable(container, {
data: [],
height: 'auto',
colHeaders: true,
rowHeaders: true,
navigableHeaders: true,
dropdownMenu: true,
filters: true,
emptyDataState: true,
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
import Handsontable from 'handsontable';
const container = document.getElementById('example1') as HTMLElement;
new Handsontable(container, {
data: [], // Empty data to trigger empty state
height: 'auto',
colHeaders: true,
rowHeaders: true,
navigableHeaders: true,
dropdownMenu: true,
filters: true,
emptyDataState: true, // Enable empty data state with default settings
licenseKey: 'non-commercial-and-evaluation',
});

Custom configuration

The empty data state supports customization of the title, description, and action buttons.

JavaScript
// Custom configuration example for Empty Data State plugin
// This example shows how to customize the empty data state message
import Handsontable from 'handsontable';
const container = document.getElementById('example2');
const hot = new Handsontable(container, {
data: [],
height: 'auto',
colHeaders: ['First Name', 'Last Name', 'Email'],
rowHeaders: true,
navigableHeaders: true,
dropdownMenu: true,
filters: true,
emptyDataState: {
message: {
title: 'No data available',
description: 'Please add some data to get started.',
buttons: [
{
text: 'Add Sample Data',
type: 'primary',
callback: () => {
// Add some sample data
hot.loadData([
['John', 'Doe', 'john@example.com'],
['Jane', 'Smith', 'jane@example.com'],
['Bob', 'Johnson', 'bob@example.com'],
['Alice', 'Johnson', 'alice@example.com'],
]);
},
},
],
},
},
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
// Custom configuration example for Empty Data State plugin
// This example shows how to customize the empty data state message
import Handsontable from 'handsontable';
const container = document.getElementById('example2') as HTMLElement;
const hot = new Handsontable(container, {
data: [], // Empty data to trigger empty state
height: 'auto',
colHeaders: ['First Name', 'Last Name', 'Email'],
rowHeaders: true,
navigableHeaders: true,
dropdownMenu: true,
filters: true,
emptyDataState: {
message: {
title: 'No data available',
description: 'Please add some data to get started.',
buttons: [
{
text: 'Add Sample Data',
type: 'primary',
callback: () => {
// Add some sample data
hot.loadData([
['John', 'Doe', 'john@example.com'],
['Jane', 'Smith', 'jane@example.com'],
['Bob', 'Johnson', 'bob@example.com'],
['Alice', 'Johnson', 'alice@example.com'],
]);
},
},
],
},
},
licenseKey: 'non-commercial-and-evaluation',
});

Dynamic messages based on source

You can provide different messages based on the source of the empty state (e.g., filters vs. no data). This allows for more contextual user guidance.

JavaScript
// Dynamic messages based on source example for Empty Data State plugin
// This example shows how to provide different messages based on the source of empty state
import Handsontable from 'handsontable';
const container = document.getElementById('example3');
const hot = new Handsontable(container, {
data: [],
height: 'auto',
colHeaders: ['First Name', 'Last Name', 'Email'],
rowHeaders: true,
navigableHeaders: true,
dropdownMenu: true,
filters: true,
contextMenu: true,
emptyDataState: {
message: (source) => {
switch (source) {
case 'filters':
return {
title: 'No results found',
description: 'Your current filters are hiding all results. Try adjusting your search criteria.',
buttons: [
{
text: 'Clear Filters',
type: 'secondary',
callback: () => {
const filtersPlugin = hot.getPlugin('filters');
if (filtersPlugin) {
filtersPlugin.clearConditions();
filtersPlugin.filter();
}
},
},
],
};
default:
return {
title: 'No data available',
description: "There's nothing to display yet. Add some data to get started.",
buttons: [
{
text: 'Add Sample Data',
type: 'primary',
callback: () => {
hot.loadData([
['John', 'Doe', 'john@example.com'],
['Jane', 'Smith', 'jane@example.com'],
['Bob', 'Johnson', 'bob@example.com'],
['Alice', 'Johnson', 'alice@example.com'],
]);
},
},
],
};
}
},
},
licenseKey: 'non-commercial-and-evaluation',
});
TypeScript
// Dynamic messages based on source example for Empty Data State plugin
// This example shows how to provide different messages based on the source of empty state
import Handsontable from 'handsontable';
const container = document.getElementById('example3') as HTMLElement;
const hot = new Handsontable(container, {
data: [],
height: 'auto',
colHeaders: ['First Name', 'Last Name', 'Email'],
rowHeaders: true,
navigableHeaders: true,
dropdownMenu: true,
filters: true,
contextMenu: true,
emptyDataState: {
message: (source: string) => {
switch (source) {
case 'filters':
return {
title: 'No results found',
description: 'Your current filters are hiding all results. Try adjusting your search criteria.',
buttons: [
{
text: 'Clear Filters',
type: 'secondary',
callback: () => {
const filtersPlugin = hot.getPlugin('filters');
if (filtersPlugin) {
filtersPlugin.clearConditions();
filtersPlugin.filter();
}
},
},
],
};
default:
return {
title: 'No data available',
description: "There's nothing to display yet. Add some data to get started.",
buttons: [
{
text: 'Add Sample Data',
type: 'primary',
callback: () => {
hot.loadData([
['John', 'Doe', 'john@example.com'],
['Jane', 'Smith', 'jane@example.com'],
['Bob', 'Johnson', 'bob@example.com'],
['Alice', 'Johnson', 'alice@example.com'],
]);
},
},
],
};
}
},
},
licenseKey: 'non-commercial-and-evaluation',
});

Localize empty data state

Translate default empty data state labels using the global translations mechanism. The empty data state plugin introduces the following keys to the language dictionary that you can use to translate the empty state UI:

KeyDefault Value
EMPTY_DATA_STATE_TITLE'No data available'
EMPTY_DATA_STATE_DESCRIPTION'There's nothing to display yet.'
EMPTY_DATA_STATE_TITLE_FILTERS'No results found'
EMPTY_DATA_STATE_DESCRIPTION_FILTERS'It looks like your current filters are hiding all results.'
EMPTY_DATA_STATE_BUTTONS_FILTERS_RESET'Reset filters'

To learn more about the translation mechanism, see the Languages guide.