gantt-diagram
JavaScript

[Tutorial] How to implement a Gantt diagram with ReactJs?

Introduction

The Gantt diagram (chart) can be very impressive for people. It seems very hard to create a diagram on your website or your web app. It’s not easy but you have very good libraries to do it. The goal of this tutorial is to create this one :

Which library chooses?

I use two libraries to create a Gantt diagram :

Google chart is very useful to create the chart for just showing data. If you would like to update tasks, create links, any complex action, it’s not adapted. I advise you to use it if you want a very simple the diagram, it’s a good solution.

Dhtmlx is the best way to create a diagram in your app. We have a lot of options to custom your diagram. In this tutorial, we will create a very simple version of the Gantt diagram with Dhtmlx.

Install dependencies

First of all, you have to install dependencies.

If you don’t have an environment in react js, you can create your project with Create React App

You have to use command npm or yarn to install dhtmlx-gantt :

npm install dhtmlx-gantt

or

yarn add dhtmlx-gantt

The structure of data

dhtmlx-gantt use specific structure of data, something like that :

const data = {
  data: [
    { id: 1, text: 'Task #1', start_date: '2020-02-12', duration: 3, progress: 0.6 },
    { id: 2, text: 'Task #2', start_date: '2020-02-16', duration: 3, progress: 0.4 },
  ],
  links: [
    { id: 1, source: 1, target: 2, type: '0' }
  ]
};

Your object has two properties :

  • data to manage tasks
  • links to manage relations between tasks.

You have properties for each task :

  • text for the name
  • start_date for the date
  • duration
  • progress to set the advancement of the task (from 0 to 1)

You have properties for each link, too :

  • source for the first task
  • the target for the second task
  • type for the type of link (you have 4 types, end to end, start to end, end to start, start to start)

Define your chart

You have to import the library

import { gantt } from 'dhtmlx-gantt';
import 'dhtmlx-gantt/codebase/skins/dhtmlxgantt_material.css';
  componentDidMount() {
    gantt.config.xml_date = "%Y-%m-%d %H:%i";
    const { tasks } = this.props;

    gantt.init(this.ganttContainer);
    this.initGanttDataProcessor();
    gantt.parse(tasks);
  }

  componentWillUnmount() {
    if (this.dataProcessor) {
      this.dataProcessor.destructor();
      this.dataProcessor = null;
    }
  }

First of all, you would like to config the format of your data with gantt.config.xml_date.

After that, you will init your chart with Gantt.init.

To parse your chart with your tasks, just use gantt.parse(tasks).

initGanttDataProcessor is the function to keep event from the Gantt. In the next tutorial, we will see how to connect firebase with our Gantt diagram by initGanttDataProcessor. (You could see the code for initGanttDataProcessor at the end of this article)

When your component will unmount, just destroy the data processor.

Render your chart

To render your chart, just call in div after defining ganttContainer.

  render() {
    return (
      <div
        ref={(input) => { this.ganttContainer = input }}
        style={{ width: '100%', height: '100%' }}
      ></div>
    );
  }

Conclusion

Gantt component

import React, { Component } from 'react';
import { gantt } from 'dhtmlx-gantt';
import 'dhtmlx-gantt/codebase/skins/dhtmlxgantt_material.css';

export default class Gantt extends Component {

  // instance of gantt.dataProcessor
  dataProcessor = null;

  initGanttDataProcessor() {
    /**
     * type: "task"|"link"
     * action: "create"|"update"|"delete"
     * item: data object object
     */
    const onDataUpdated = this.props.onDataUpdated;
    this.dataProcessor = gantt.createDataProcessor((type, action, item, id) => {
      return new Promise((resolve, reject) => {
        if (onDataUpdated) {
          onDataUpdated(type, action, item, id);
        }

        // if onDataUpdated changes returns a permanent id of the created item, you can return it from here so dhtmlxGantt could apply it
        // resolve({id: databaseId});
        return resolve();
      });
    });
  }

  componentDidMount() {
    gantt.config.xml_date = "%Y-%m-%d %H:%i";
    const { tasks, options } = this.props;

    //Define options
    gantt.config.readonly = options?.readonly;

    gantt.init(this.ganttContainer);
    this.initGanttDataProcessor();
    gantt.parse(tasks);
  }

  componentWillUnmount() {
    if (this.dataProcessor) {
      this.dataProcessor.destructor();
      this.dataProcessor = null;
    }
  }

  render() {
    return (
      <div
        ref={(input) => { this.ganttContainer = input }}
        style={{ width: '100%', height: '100%' }}
      ></div>
    );
  }
}

GanttView component

import React, { Component } from 'react'
import { gantt } from 'dhtmlx-gantt';
import Gantt from '.';


const data = {
  data: [
    { id: 1, text: 'Task #1', start_date: '2020-02-12', duration: 3, progress: 0.6 },
    { id: 2, text: 'Task #2', start_date: '2020-02-16', duration: 3, progress: 0.4 },
  ],
  links: [
    { id: 1, source: 1, target: 2, type: '0' }
  ]
};

export default class GanttView extends Component {

    constructor(props) {
        super(props);
        this.state = {
            tasks:null,
        };
     }

    componentDidMount(){
        this._getTaskAsync();
    }

    onDataUpdated(type, action, item, id){
        let actionMain = {type, action, item, id};
    }

    _getTaskAsync(){
        /* Mock Data */
        this.setState({tasks: data});

    }

    render() {
        return (
            <div>
                {   this.state.tasks ? <div className="gantt-container">
                    <Gantt
                    tasks={data}
                    onDataUpdated={this.onDataUpdated}
                    />
                </div> : null}
            </div>
        )
    }
}

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *