Search results

State Persistence in React Gantt component

22 Nov 2022 / 6 minutes to read

State persistence refers to the Gantt’s state maintained in the browser’s localStorage even if the browser is refreshed or if you move to the next page within the browser. State persistence stores gantt’s model object in the local storage when the enablePersistence is defined as true.

Get or set localStorage value

If the enablePersistence property is set to true, the gantt property value is saved in the window.localStorage for reference. You can get/set the localStorage value by using the getItem/setItem method in the window.localStorage.

Copied to clipboard
//get the Gantt model.
let value: string = window.localStorage.getItem('ganttGantt'); //"ganttGantt" is component name + component id.
let model: Object = JSON.parse(model);
Copied to clipboard
//set the Gantt model.
window.localStorage.setItem('ganttGantt', JSON.stringify(model)); //"ganttGantt" is component name + component id.

You can refer to our React Gantt feature tour page for its groundbreaking feature representations. You can also explore our React Gantt example to knows how to present and manipulate data.

Prevent columns from persisting

When the enablePersistence property is set to true, the Gantt properties such as Filtering, Sorting , and Columns will persist. You can use the addOnPersist method to prevent these Gantt properties from persisting.

The following example demonstrates how to prevent Gantt columns from persisting. In the dataBound event of the Gantt, you can override the addOnPersist method and remove the columns from the key list given for persistence.

Note: 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.

Source
Preview
index.jsx
index.html
index.tsx
Copied to clipboard
let data = [
    {
        TaskID: 1,
        TaskName: 'Project Initiation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
            { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
            { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
        ]
    },
    {
        TaskID: 5,
        TaskName: 'Project Estimation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
            { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
            { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
        ]
    },
];
import { GanttComponent, ColumnsDirective, ColumnDirective } from '@syncfusion/ej2-react-gantt';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as React from 'react';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.taskFields = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
    }
    dataBound() {
        let cloned = this.gantt.addOnPersist;
        this.gantt.addOnPersist = function (key) {
            key = key.filter((item) => item !== "columns");
            return cloned.call(this, key);
        };
    }
    addColumn() {
        let obj = { field: "Progress", headerText: 'Progress', width: 100 };
        this.gantt.columns.push(obj); //you can add the columns by using the Gantt columns method
        this.gantt.treeGrid.refreshColumns();
    }
    removeColumn() {
        this.gantt.columns.pop();
        this.gantt.treeGrid.refreshColumns();
    }
    render() {
        this.dataBound = this.dataBound.bind(this);
        this.addColumn = this.addColumn.bind(this);
        this.removeColumn = this.removeColumn.bind(this);
        return (<div> <ButtonComponent onClick={this.addColumn}>Add Columns</ButtonComponent>
      <ButtonComponent onClick={this.removeColumn}>Remove Columns</ButtonComponent><GanttComponent id="Gantt" dataSource={data} enablePersistence={true} dataBound={this.dataBound} height={430} taskFields={this.taskFields} ref={g => this.gantt = g}>
          <ColumnsDirective>
              <ColumnDirective field='TaskID' width='100'/>
              <ColumnDirective field='TaskName' width='100'/>
              <ColumnDirective field='StartDate' width='100'/>
              <ColumnDirective field='Duration' width='100'/>
          </ColumnsDirective>
      </GanttComponent></div>);
    }
}
;
ReactDOM.render(<App />, document.getElementById('root'));
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/20.3.56/material.css" rel="stylesheet" type="text/css"/>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
     <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }
    </style>
</head>

<body>
        <div id='root'>
            <div id='loader'>Loading....</div>
        </div>
</body>

</html>
Copied to clipboard
let data: Object[]  = [
            {
              TaskID: 1,
              TaskName: 'Project Initiation',
              StartDate: new Date('04/02/2019'),
              EndDate: new Date('04/21/2019'),
              subtasks: [
                    { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                    { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50  },
                    { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
               ]
            },
            {
             TaskID: 5,
             TaskName: 'Project Estimation',
             StartDate: new Date('04/02/2019'),
             EndDate: new Date('04/21/2019'),
             subtasks: [
                   { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                  { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                   { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
                ]
            },
        ];

import { GanttComponent,ColumnsDirective,ColumnDirective } from '@syncfusion/ej2-react-gantt';
import { Gantt} from '@syncfusion/ej2-react-gantt';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as React from 'react';

export default class App extends React.Component<{}, {}>{
  private gantt: Gantt | null;
  public dataBound(){
    let cloned =  this.gantt.addOnPersist;
    this.gantt.addOnPersist = function (key: any) {
        key = key.filter((item: string)  => item !== "columns");
        return cloned.call(this, key);
    };
  }
  public addColumn(){
    let obj = { field: "Progress", headerText: 'Progress', width: 100 };
    this.gantt.columns.push(obj as any); //you can add the columns by using the Gantt columns method
    this.gantt.treeGrid.refreshColumns();
  }
  public removeColumn(){
    this.gantt.columns.pop();
    this.gantt.treeGrid.refreshColumns();
  }
  public taskFields: any = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    child: 'subtasks'
  };
  public render() {
      this.dataBound = this.dataBound.bind(this);
      this.addColumn = this.addColumn.bind(this);
      this.removeColumn = this.removeColumn.bind(this);
      return( <div> <ButtonComponent onClick= { this.addColumn }>Add Columns</ButtonComponent>
      <ButtonComponent onClick= { this.removeColumn }>Remove Columns</ButtonComponent><GanttComponent id="Gantt" dataSource={data} enablePersistence={true} dataBound={this.dataBound} height={430} taskFields={this.taskFields}
      ref={g => this.gantt = g}>
          <ColumnsDirective>
              <ColumnDirective field='TaskID' width='100'/>
              <ColumnDirective field='TaskName' width='100'/>
              <ColumnDirective field='StartDate' width='100'/>
              <ColumnDirective field='Duration' width='100'/>
          </ColumnsDirective>
      </GanttComponent></div>)
  }
};
ReactDOM.render(<App />, document.getElementById('root'));

Persist the header template and header Text

By default, the Gantt properties such as column template, header text, header template, column formatter, and value accessor will not persist when enablePersistence is set to true. Because the column template and header text can be customized at the application level.

If you wish to restore all these column properties, then you can achieve it by cloning the gantt columns property using JavaScript Object’s assign method and storing this along with the persist data manually. While restoring the settings, this column object must be assigned to the gantt’s columns property to restore the column settings as demonstrated in the following sample.

Source
Preview
index.jsx
index.html
index.tsx
Copied to clipboard
let data = [
    {
        TaskID: 1,
        TaskName: 'Project Initiation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
            { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
            { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
        ]
    },
    {
        TaskID: 5,
        TaskName: 'Project Estimation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
            { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
            { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
        ]
    },
];
import { ColumnDirective, ColumnsDirective, GanttComponent } from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as ReactDOM from 'react-dom';
import * as React from 'react';
export default class App extends React.Component {
    constructor() {
        super(...arguments);
        this.headerTemplate = this.customerTemplate;
        this.taskFields = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
    }
    clickHandler() {
        let savedProperties = JSON.parse(this.gantt.getPersistData());
        let gridColumnsState = Object.assign([], this.gantt.ganttColumns);
        savedProperties.columns.forEach((col) => {
            let headerText = gridColumnsState.find((colColumnsState) => colColumnsState.field === col.field)['headerText'];
            let colTemplate = gridColumnsState.find((colColumnsState) => colColumnsState.field === col.field)['template'];
            let headerTemplate = gridColumnsState.find((colColumnsState) => colColumnsState.field === col.field)['headerTemplate'];
            col.headerText = 'Text Changed';
            col.template = colTemplate;
            col.headerTemplate = headerTemplate; //likewise you can restore required column properties as per your wants.
        });
        console.log(savedProperties);
        this.gantt.treeGrid.setProperties(savedProperties);
    }
    customerTemplate(props) {
        return (<div>
          <span className="e-icons e-header"></span>Task Name
       </div>);
    }
    render() {
        this.clickHandler = this.clickHandler.bind(this);
        return (<div> <ButtonComponent onClick={this.clickHandler}>Restore</ButtonComponent> <GanttComponent id="Gantt" dataSource={data} taskFields={this.taskFields} enablePersistence={true} height={230} ref={g => this.gantt = g}>
          <ColumnsDirective>
              <ColumnDirective field='TaskID' width='100' textAlign="Right"/>
              <ColumnDirective field='TaskName' width='100' headerTemplate={this.headerTemplate}/>
              <ColumnDirective field='StartDate' width='100'/>
              <ColumnDirective field='Duration' width='100'/>
          </ColumnsDirective>
      </GanttComponent></div>);
    }
}
;
ReactDOM.render(<App />, document.getElementById('root'));
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion React Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Essential JS 2 for React Components" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/20.3.56/material.css" rel="stylesheet" type="text/css"/>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
     <style>
        #loader {
            color: #008cff;
            height: 40px;
            left: 45%;
            position: absolute;
            top: 45%;
            width: 30%;
        }
    </style>
</head>

<body>
        <div id='root'>
            <div id='loader'>Loading....</div>
        </div>
</body>

</html>
Copied to clipboard
let data: Object[]  = [
            {
              TaskID: 1,
              TaskName: 'Project Initiation',
              StartDate: new Date('04/02/2019'),
              EndDate: new Date('04/21/2019'),
              subtasks: [
                    { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                    { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50  },
                    { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
               ]
            },
            {
             TaskID: 5,
             TaskName: 'Project Estimation',
             StartDate: new Date('04/02/2019'),
             EndDate: new Date('04/21/2019'),
             subtasks: [
                   { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                  { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                   { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
                ]
            },
        ];

import { ColumnDirective, ColumnsDirective, GanttComponent } from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { Gantt} from '@syncfusion/ej2-react-gantt';
import * as ReactDOM from 'react-dom';
import * as React from 'react';

export default class App extends React.Component<{}, {}>{
  private gantt: Gantt | null;
  public clickHandler(){
    let savedProperties = JSON.parse(this.gantt.getPersistData());
    let gridColumnsState = Object.assign([], this.gantt.ganttColumns);
    savedProperties.columns.forEach((col: {
        field: any;
        headerText: any;
        template: any;
        headerTemplate: any;
    }) => {
        let headerText = gridColumnsState.find((colColumnsState) => colColumnsState.field === col.field)['headerText'];
        let colTemplate = gridColumnsState.find((colColumnsState) => colColumnsState.field === col.field)['template'];
        let headerTemplate = gridColumnsState.find((colColumnsState) => colColumnsState.field === col.field)['headerTemplate'];
        col.headerText = 'Text Changed';
        col.template = colTemplate;
        col.headerTemplate = headerTemplate; //likewise you can restore required column properties as per your wants.
    }
  );
    console.log(savedProperties);
    this.gantt.treeGrid.setProperties(savedProperties);
  }
  public headerTemplate: any = this.customerTemplate;
  public customerTemplate(props: any): any {
     return (<div>
          <span className="e-icons e-header" ></span>Task Name
       </div>);
  }
  public taskFields: any = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    child: 'subtasks'
  };
  public render() {
      this.clickHandler = this.clickHandler.bind(this);
      return( <div> <ButtonComponent onClick= { this.clickHandler }>Restore</ButtonComponent> <GanttComponent id="Gantt" dataSource={data}
      taskFields={this.taskFields} enablePersistence={true} height={230}
      ref={g => this.gantt = g}>
          <ColumnsDirective>
              <ColumnDirective field='TaskID' width='100' textAlign="Right"/>
              <ColumnDirective field='TaskName' width='100' headerTemplate={this.headerTemplate}/>
              <ColumnDirective field='StartDate' width='100'/>
              <ColumnDirective field='Duration' width='100'/>
          </ColumnsDirective>
      </GanttComponent></div>)
  }
};
ReactDOM.render(<App />, document.getElementById('root'));