State Persistence in EJ2 JavaScript Gantt Chart Control

30 Jun 202624 minutes to read

The Syncfusion® EJ2 JavaScript 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 JavaScript 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.

var ganttChart = new ej.gantt.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' }
    ]
});

ej.gantt.Gantt.Inject(ej.gantt.Toolbar, ej.gantt.Edit, ej.gantt.Sort, ej.gantt.Filter);

ganttChart.appendTo('#TaskDetails');

var restoreBtn = new ej.buttons.Button();
restoreBtn.appendTo('#restore');

document.getElementById('restore').addEventListener('click', function () {
    var id = 'TaskDetails' + Math.floor(Math.random() * 10);
    ganttChart.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.2.2/tailwind3.css" rel="stylesheet" type="text/css">
  <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
  <script src="es5-datasource.js" type="text/javascript"></script>
</head>

<body>
  <div id="container">
    <div style="margin-bottom: 20px;">
      <button id="restore">Restore</button>
    </div>
    <div id="TaskDetails"></div>
  </div>
  <script>
    var ele = document.getElementById('container');
    if (ele) {
      ele.style.visibility = "visible";
    }
  </script>
  <script src="index.js" type="text/javascript"></script>
</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.

var ganttChart = new ej.gantt.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' }
    ]
});

ganttChart.appendTo('#Gantt');

document.getElementById('restore').addEventListener('click', function () {
    ganttChart.enablePersistence = false;
    window.localStorage.setItem('ganttGantt', '');
    ganttChart.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.2.2/tailwind3.css" rel="stylesheet" type="text/css">
  <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
  <script src="es5-datasource.js" type="text/javascript"></script>
</head>

<body>
  <div id="container">
    <div style="margin-bottom: 20px;">
      <button id="restore">Restore</button>
    </div>
    <div id="Gantt"></div>
  </div>
  <script>
    var ele = document.getElementById('container');
    if (ele) {
      ele.style.visibility = "visible";
    }
  </script>
  <script src="index.js" type="text/javascript"></script>
</body>

</html>

Restore to previous state

The Syncfusion® EJ2 JavaScript 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.

ej.gantt.Gantt.Inject(ej.gantt.Toolbar, ej.gantt.Edit, ej.gantt.Sort, ej.gantt.Filter);

var ganttChart = new ej.gantt.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' }
    ]
});

ganttChart.appendTo('#Gantt');

var saveBtn = new ej.buttons.Button();
saveBtn.appendTo('#saveBtn');

var restoreBtn = new ej.buttons.Button();
restoreBtn.appendTo('#restoreBtn');

document.getElementById('saveBtn').addEventListener('click', function () {
    var persistData = ganttChart.getPersistData();
    if (persistData) {
        localStorage.setItem('ganttTaskDetails', persistData);
    }
});

document.getElementById('restoreBtn').addEventListener('click', function () {
    var value = localStorage.getItem('ganttTaskDetails');
    if (value) {
        var state = JSON.parse(value);
        ganttChart.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.2.2/tailwind3.css" rel="stylesheet" type="text/css">
  <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
  <script src="es5-datasource.js" type="text/javascript"></script>
</head>

<body>
  <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>
  <script>
    var ele = document.getElementById('container');
    if (ele) {
      ele.style.visibility = "visible";
    }
  </script>
  <script src="index.js" type="text/javascript"></script>
</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.

var ganttChart = new ej.gantt.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 () {
            var originalPersist = this.addOnPersist;
            this.addOnPersist = function (keys) {
                var filteredKeys = keys.filter(function (key) {
                    return key !== 'columns';
                });
                return originalPersist.call(this, filteredKeys);
            };
        }
    });

    ganttChart.appendTo('#Gantt');

    var addBtn = new ej.buttons.Button();
    addBtn.appendTo('#add');

    var removeBtn = new ej.buttons.Button();
    removeBtn.appendTo('#remove');

    document.getElementById('add').onclick = function () {
        ganttChart.columns.push({
            field: 'Progress',
            headerText: 'Progress',
            width: 100
        });
        ganttChart.refresh();
    };

    document.getElementById('remove').onclick = function () {
        ganttChart.columns.pop();
        ganttChart.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.2.2/tailwind3.css" rel="stylesheet" type="text/css">
    <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
    <script src="es5-datasource.js" type="text/javascript"></script>
</head>

<body>
    <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>
    <script>
        var ele = document.getElementById('container');
        if (ele) {
            ele.style.visibility = "visible";
        }   
    </script>
    <script src="index.js" type="text/javascript"></script>
</body>

</html>

Add to persist

Persistence in the Syncfusion® EJ2 JavaScript 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.

var ganttChart = new ej.gantt.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 }
    ],
});

ganttChart.appendTo('#Gantt');

var addBtn = new ej.buttons.Button();
addBtn.appendTo('#add');

var removeBtn = new ej.buttons.Button();
removeBtn.appendTo('#remove');

document.getElementById('add').addEventListener('click', function () {
    ganttChart.columns.push({
        field: 'Progress',
        headerText: 'Progress',
        width: 100
    });
    ganttChart.refresh();
});

document.getElementById('remove').addEventListener('click', function () {
    ganttChart.columns.pop();
    ganttChart.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.2.2/tailwind3.css" rel="stylesheet" type="text/css">
  <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
  <script src="es5-datasource.js" type="text/javascript"></script>
</head>

<body>
  <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>
  <script>
    var ele = document.getElementById('container');
    if (ele) {
      ele.style.visibility = "visible";
    }
  </script>
  <script src="index.js" type="text/javascript"></script>
</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.

var ganttChart = new ej.gantt.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' }
    ]
});

ganttChart.appendTo('#Gantt');

var restoreBtn = new ej.buttons.Button();
restoreBtn.appendTo('#restore');

document.getElementById('restore').addEventListener('click', function () {
    var savedProperties = JSON.parse(ganttChart.getPersistData());
    var gridColumnsState = ganttChart.ganttColumns.slice();

    savedProperties.columns.forEach(function (col) {
        var state = gridColumnsState.find(function (c) {
            return c.field === col.field;
        });
        if (state) {
            col.headerText = 'Text Changed';
            col.template = state.template;
            col.headerTemplate = state.headerTemplate;
        }
    });

    ganttChart.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.2.2/tailwind3.css" rel="stylesheet" type="text/css">
        <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
        <script src="es5-datasource.js" type="text/javascript"></script>
    </head>

    <body>
        <div id="container">
            <button id="restore">Restore</button>
            <div id="Gantt"></div>      
        </div>

        <script>
            var ele = document.getElementById('container');
            if(ele) {
            ele.style.visibility = "visible";
            }   
        </script>
        <script src="index.js" type="text/javascript"></script>
    </body>
</html>