State Persistence in EJ2 TypeScript Gantt Chart Control
24 Jul 202624 minutes to read
The Syncfusion® EJ2 TypeScript Gantt Chart control supports state management to retain its configuration and data after a browser refresh during the same session.
To enable this, set the enablePersistence property to true. Once enabled, the control saves its state in the browser’s localStorage and restores it automatically after page reloads.
Restore initial Gantt state
The Syncfusion® EJ2 TypeScript Gantt Chart control provides options to reset its state, reverting all interactions and configurations to the original setup. This is useful for clearing filters, sorting, and column arrangements, even when enablePersistence is enabled.
Changing control ID
To reset the Gantt to its default state, update the control ID. This initializes the control as a new instance, restoring its original configuration.
Here is an example code to change the control ID dynamically to restore initial Gantt state.
import { Gantt, Toolbar, Edit, Sort, Filter } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { data } from './datasource.ts';
Gantt.Inject(Toolbar, Edit, Sort, Filter);
let gantt: Gantt = new Gantt({
dataSource: data,
height: '430px',
enablePersistence: true,
allowSorting: true,
allowFiltering: true,
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
},
splitterSettings: {
columnIndex: 2
},
editSettings: {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
},
toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel', 'Search', 'ExpandAll', 'CollapseAll', 'PrevTimeSpan', 'NextTimeSpan', 'Indent', 'Outdent'],
columns: [
{ field: 'TaskID', width: 90, textAlign: 'Right' },
{ field: 'TaskName', width: 290 },
{ field: 'StartDate', width: 390, format: 'yMd', textAlign: 'Right' },
{ field: 'Duration', width: 120, textAlign: 'Right' },
{ field: 'Progress', width: 120, textAlign: 'Right' }
]
});
gantt.appendTo('#TaskDetails');
let restoreBtn: Button = new Button();
restoreBtn.appendTo('#restore');
(document.getElementById('restore') as any).addEventListener('click', () => {
const id = 'TaskDetails' + Math.floor(Math.random() * 10);
gantt.element.id = id;
location.reload();
});<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Gantt Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div style="margin-bottom: 20px;">
<button id="restore">Restore</button>
</div>
<div id='TaskDetails'></div>
</div>
</body>
</html>Clearing local storage
Clearing the browser’s local storage associated with the Gantt Chart control removes all persisted data, allowing it to load with its initial settings.
Here is an example code on how to clear local storage to retain its default state.
import { Gantt, Toolbar, Edit, Filter } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { data } from './datasource.ts';
Gantt.Inject(Toolbar, Edit, Filter);
let gantt: Gantt = new Gantt({
dataSource: data,
height: '430px',
allowFiltering: true,
enablePersistence: true,
splitterSettings: { columnIndex: 2 },
editSettings: {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
},
toolbar: ['Add', 'Edit', 'Delete', 'Update', 'Cancel', 'ExpandAll', 'CollapseAll', 'PrevTimeSpan', 'NextTimeSpan', 'Indent', 'Outdent'],
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
},
columns: [
{ field: 'TaskID', width: 90, textAlign: 'Right' },
{ field: 'TaskName', width: 290 },
{ field: 'StartDate', width: 390, format: 'yMd', textAlign: 'Right' },
{ field: 'Duration', width: 120, textAlign: 'Right' },
{ field: 'Progress', width: 120, textAlign: 'Right' }
]
});
gantt.appendTo('#Gantt');
let restoreBtn: Button = new Button();
restoreBtn.appendTo('#restore');
(document.getElementById('restore') as HTMLElement).addEventListener('click', () => {
gantt.enablePersistence = false;
window.localStorage.setItem('ganttGantt', '');
gantt.destroy();
location.reload();
});<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Gantt Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div style="margin-bottom: 20px;">
<button id="restore">Restore</button>
</div>
<div id='Gantt'></div>
</div>
</body>
</html>Restore to previous state
The Syncfusion® EJ2 TypeScript Gantt Chart control allows saving and restoring its state using local storage, ensuring retention of configurations like column order, sorting, and filtering.
To implement this functionality, extract the current state using getPersistData, store it with setItem, retrieve it via getItem, and apply it using setProperties to restore the saved configuration.
import { Gantt, Edit, Toolbar, Sort, Filter } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { data } from './datasource.ts';
Gantt.Inject(Edit, Toolbar, Sort, Filter);
let gantt: Gantt = new Gantt({
dataSource: data,
height: '430px',
allowSorting: true,
allowFiltering: true,
enablePersistence: true,
toolbar: ['Add','Edit','Delete','Update','Cancel','Search','ExpandAll','CollapseAll','PrevTimeSpan','NextTimeSpan','Indent','Outdent'],
editSettings: {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
},
splitterSettings: { columnIndex: 2 },
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
},
columns: [
{ field: 'TaskID', width: 90, textAlign: 'Right' },
{ field: 'TaskName', width: 290 },
{ field: 'StartDate', width: 390, format: 'yMd', textAlign: 'Right' },
{ field: 'Duration', width: 120, textAlign: 'Right' }
]
});
gantt.appendTo('#Gantt');
let saveBtn: Button = new Button({ cssClass: 'e-success' });
saveBtn.appendTo('#saveBtn');
let restoreBtn: Button = new Button({ cssClass: 'e-danger' });
restoreBtn.appendTo('#restoreBtn');
document.getElementById('saveBtn')!.addEventListener('click', () => {
const persistData = gantt.getPersistData();
if (persistData) {
localStorage.setItem('ganttTaskDetails', persistData);
}
});
document.getElementById('restoreBtn')!.addEventListener('click', () => {
const value = localStorage.getItem('ganttTaskDetails');
if (value) {
const state = JSON.parse(value);
gantt.treeGrid.setProperties(state);
}
});<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Gantt Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<button id="saveBtn" class="e-btn e-success" style="margin-right:10px;">Save</button>
<button id="restoreBtn" class="e-btn e-danger">Restore</button>
<div id="Gantt" style="margin-top:20px;"></div>
</div>
</body>
</html>Get or set localStorage value
When enablePersistence is set to true, the Gantt Chart control state is stored in window.localStorage. The stored data can be retrieved or updated using the getItem and setItem methods available in the browser’s localStorage.
//get the Gantt model.
let value: string = window.localStorage.getItem('ganttGantt'); //"ganttGantt" is control name + control ID.
let model: Object = JSON.parse(model);//set the Gantt model.
window.localStorage.setItem('ganttGantt', JSON.stringify(model)); //"ganttGantt" is control name + control ID.You can refer to our JavaScript Gantt feature tour page for its groundbreaking feature representations. You can also explore our JavaScript Gantt example to knows how to present and manipulate data.
Prevent columns from persisting
When enablePersistence is set to true, Gantt properties such as Filtering, Sorting, and Columns are automatically saved.
To prevent specific properties from being persisted, use the addOnPersist method.
When the enablePersistence property is set to true, the Gantt features such as column template, column formatter, header text, and value accessor will not persist.
The example below shows how to prevent Gantt columns from being persisted. In the dataBound event, override the addOnPersist method and remove Columns from the persistence key list.
import { Gantt } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { GanttData } from './datasource.ts';
let gantt: Gantt = new Gantt({
dataSource: GanttData,
height: '430px',
enablePersistence: true,
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
},
columns: [
{ field: 'TaskID', headerText: 'Task ID', textAlign: 'Right', width: 120 },
{ field: 'TaskName', headerText: 'Task Name', width: 150 },
{ field: 'StartDate', headerText: 'Start Date', width: 150 },
{ field: 'Duration', headerText: 'Duration', width: 150 },
{ field: 'Progress', headerText: 'Progress', width: 150 }
],
dataBound: function () {
const originalPersist = (this as any).addOnPersist;
(this as any).addOnPersist = (keys: string[]) => {
const filteredKeys = keys.filter(key => key !== 'columns');
return originalPersist.call(this, filteredKeys);
};
}
});
gantt.appendTo('#Gantt');
let addBtn: Button = new Button();
addBtn.appendTo('#add');
let removeBtn: Button = new Button();
removeBtn.appendTo('#remove');
document.getElementById('add')!.addEventListener('click', () => {
(gantt.columns as any).push({
field: 'Progress',
headerText: 'Progress',
width: 100
});
gantt.refresh();
});
document.getElementById('remove')!.addEventListener('click', () => {
(gantt.columns as any).pop();
gantt.refresh();
});<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Gantt Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id="container">
<div style="margin-bottom: 16px;">
<button id="add" style="margin-right: 8px;">Add Column</button>
<button id="remove">Remove Column</button>
</div>
<div id="Gantt"></div>
</div>
</body>
</html>Add to persist
Persistence in the Syncfusion® EJ2 TypeScript Gantt Chart control enables storing and restoring the control state. It supports preserving column layout, sorting, filtering, and configuration elements such as column templates, header templates, and header text, ensuring consistent behavior across sessions.
Add a new column in persisted columns list
When enablePersistence is set to true in the Syncfusion Gantt Chart control, column configurations are saved automatically. To add a new column to the persisted list, update the column collection using columns.push(), then call the refreshColumns method on the treeGrid object in the Gantt instance to update the UI.
import { Gantt } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { data } from './datasource.ts';
let gantt: Gantt = new Gantt({
dataSource: data,
height: '430px',
enablePersistence: true,
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
},
columns: [
{ field: 'TaskID', headerText: 'Task ID', textAlign: 'Right', width: 120 },
{ field: 'TaskName', headerText: 'Task Name', width: 150 },
{ field: 'StartDate', headerText: 'Start Date', width: 150 },
{ field: 'Duration', headerText: 'Duration', width: 150 },
{ field: 'Progress', headerText: 'Progress', width: 150 }
],
});
gantt.appendTo('#Gantt');
let addBtn: Button = new Button();
addBtn.appendTo('#add');
let removeBtn: Button = new Button();
removeBtn.appendTo('#remove');
document.getElementById('add')!.addEventListener('click', () => {
(gantt.columns as any).push({
field: 'Progress',
headerText: 'Progress',
width: 100
});
gantt.refresh();
});
document.getElementById('remove')!.addEventListener('click', () => {
(gantt.columns as any).pop();
gantt.refresh();
});<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Gantt Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id='container'>
<div style="margin-bottom: 16px;">
<button id="add" style="margin-right: 8px;">Add Column</button>
<button id="remove">Remove Column</button>
</div>
<div id="Gantt" style="margin-top:20px;"></div>
</div>
</body>
</html>Persist the header template and header Text
By default, properties such as column template, header text, header template, formatter, and value accessor are not persisted when enablePersistence is set to true, as these are defined at the application level.
To persist these settings, clone the Columns property using Object.assign, store it manually along with the persisted data, and reassign it to the Gantt’s Columns property during restoration.
import { Gantt } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { GanttData } from './datasource.ts';
let gantt: Gantt = new Gantt({
dataSource: GanttData,
height: '430px',
enablePersistence: true,
splitterSettings: { columnIndex: 2 },
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
},
columns: [
{ field: 'TaskID', width: 90, textAlign: 'Right' },
{
field: 'TaskName',
width: 290,
headerTemplate: '<div style="width:20px;height:20px;">Tasks Name</div>'
},
{ field: 'StartDate', width: 390, format: 'yMd', textAlign: 'Right' },
{ field: 'Duration', width: 120, textAlign: 'Right' },
{ field: 'Progress', width: 120, textAlign: 'Right' }
]
});
gantt.appendTo('#Gantt');
let restoreBtn: Button = new Button();
restoreBtn.appendTo('#restore');
document.getElementById('restore')!.addEventListener('click', () => {
const savedProperties = JSON.parse(gantt.getPersistData());
const gridColumnsState = [...(gantt as any).ganttColumns];
savedProperties.columns.forEach((col: any) => {
const state = gridColumnsState.find((c: any) => c.field === col.field);
if (state) {
col.headerText = 'Text Changed';
col.template = state.template;
col.headerTemplate = state.headerTemplate;
}
});
(gantt as any).treeGrid.setProperties(savedProperties);
});<!DOCTYPE html>
<html lang="en">
<head>
<title>EJ2 Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Typescript Gantt Controls" />
<meta name="author" content="Syncfusion" />
<link href="index.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='loader'>Loading....</div>
<div id="container">
<button id="restore" style="margin-bottom:20px">Restore</button>
<div id="Gantt"></div>
</div>
</body>
</html>