Saving data
Save data after each change to the data set, using Handsontable’s API hooks. Preserve the table’s state by saving data to the local storage.
Save changes using a callback
To track changes made in your data grid, use Handsontable’s afterChange hook.
The example below handles data by using fetch. Note that this is just a mockup, and nothing is actually saved. You need to implement the server-side part by yourself.
import { useState, useRef } from 'react';import { HotTable } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent = () => { const hotRef = useRef(null); const [output, setOutput] = useState('Click "Load" to load data from server'); const [isAutosave, setIsAutosave] = useState(false); const autosaveClickCallback = (event) => { const target = event.target;
setIsAutosave(target.checked);
if (target.checked) { setOutput('Changes will be autosaved'); } else { setOutput('Changes will not be autosaved'); } };
const loadClickCallback = (event) => { const hot = hotRef.current?.hotInstance;
fetch('/docs/scripts/json/load.json').then((response) => { response.json().then((data) => { hot?.loadData(data.data); // or, use `updateData()` to replace `data` without resetting states setOutput('Data loaded'); }); }); };
const saveClickCallback = (event) => { const hot = hotRef.current?.hotInstance;
// save all cell's data fetch('/docs/scripts/json/save.json', { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data: hot?.getData() }), }).then(() => { setOutput('Data saved'); console.log('The POST request is only used here for the demo purposes'); }); };
return ( <> <div className="example-controls-container"> <div className="controls"> <button id="load" className="button button--primary button--blue" onClick={loadClickCallback}> Load data </button> <button id="save" className="button button--primary button--blue" onClick={saveClickCallback}> Save data </button> <label> <input type="checkbox" name="autosave" id="autosave" checked={isAutosave} onClick={autosaveClickCallback} /> Autosave </label> </div> <output className="console" id="output"> {output} </output> </div> <HotTable ref={hotRef} startRows={8} startCols={6} rowHeaders={true} colHeaders={true} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" afterChange={function (change, source) { if (source === 'loadData') { return; // don't save this change }
if (!isAutosave) { return; }
fetch('/docs/scripts/json/save.json', { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data: change }), }).then(() => { setOutput(`Autosaved (${change?.length} cell${(change?.length || 0) > 1 ? 's' : ''})`); console.log('The POST request is only used here for the demo purposes'); }); }} /> </> );};
export default ExampleComponent;import { useState, useRef, MouseEvent } from 'react';import { HotTable, HotTableRef } from '@handsontable/react-wrapper';import { registerAllModules } from 'handsontable/registry';import Handsontable from 'handsontable/base';
// register Handsontable's modulesregisterAllModules();
const ExampleComponent: React.FC = () => { const hotRef = useRef<HotTableRef>(null); const [output, setOutput] = useState<string>('Click "Load" to load data from server');
const [isAutosave, setIsAutosave] = useState<boolean>(false);
const autosaveClickCallback = (event: MouseEvent<HTMLInputElement>) => { const target = event.target as HTMLInputElement;
setIsAutosave(target.checked);
if (target.checked) { setOutput('Changes will be autosaved'); } else { setOutput('Changes will not be autosaved'); } };
const loadClickCallback = (event: MouseEvent<HTMLButtonElement>) => { const hot = hotRef.current?.hotInstance;
fetch('/docs/scripts/json/load.json').then((response) => { response.json().then((data) => { hot?.loadData(data.data); // or, use `updateData()` to replace `data` without resetting states setOutput('Data loaded'); }); }); };
const saveClickCallback = (event: MouseEvent<HTMLButtonElement>) => { const hot = hotRef.current?.hotInstance;
// save all cell's data fetch('/docs/scripts/json/save.json', { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data: hot?.getData() }), }).then(() => { setOutput('Data saved'); console.log('The POST request is only used here for the demo purposes'); }); };
return ( <> <div className="example-controls-container"> <div className="controls"> <button id="load" className="button button--primary button--blue" onClick={loadClickCallback}> Load data </button> <button id="save" className="button button--primary button--blue" onClick={saveClickCallback}> Save data </button> <label> <input type="checkbox" name="autosave" id="autosave" checked={isAutosave} onClick={autosaveClickCallback} /> Autosave </label> </div> <output className="console" id="output"> {output} </output> </div> <HotTable ref={hotRef} startRows={8} startCols={6} rowHeaders={true} colHeaders={true} height="auto" autoWrapRow={true} autoWrapCol={true} licenseKey="non-commercial-and-evaluation" afterChange={function (change: Handsontable.CellChange[] | null, source: Handsontable.ChangeSource) { if (source === 'loadData') { return; // don't save this change }
if (!isAutosave) { return; }
fetch('/docs/scripts/json/save.json', { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ data: change }), }).then(() => { setOutput(`Autosaved (${change?.length} cell${(change?.length || 0) > 1 ? 's' : ''})`); console.log('The POST request is only used here for the demo purposes'); }); }} /> </> );};
export default ExampleComponent;.controls { display: flex; align-items: center; flex-wrap: wrap;}Save data locally
To persist table state (e.g. column order, column widths, row order) across page reloads, use the browser’s localStorage API or sessionStorage in your application. Listen to the appropriate hooks (e.g. afterColumnMove, afterColumnResize) and save or restore state as needed.
Related API reference
Core methods
Hooks