Overview

  • This is a simple React project that will let you explore features of the React Gantt Chart component  from DayPilot Pro for JavaScript.

  • The project was generated using DayPilot UI Builder - an online application that lets you configure the Gantt Chart component and generate a new React project.

  • The Gantt Chart supports tasks, task groups and milestones.

  • The tasks can be moved using drag and drop.

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.

React Gantt Chart Component

React Gantt Chart with Tasks and Dependency Links

We will create a new GanttChart component that will wrap the DayPilotGantt component and configure its appearance and behavior.

Before we can use the DayPilotGantt component, we need to install the daypilot-pro-react package from npm.daypilot.org:

npm install https://npm.daypilot.org/daypilot-pro-react/trial/2024.3.5972.tar.gz --save

The first version of our component is very simple (src/gantt/GanttChart.js):

import React from 'react';
import {DayPilotGantt} from "daypilot-pro-react";

const GanttChart = () => {
  return (
    <div>
      <DayPilotGantt/>
    </div>
  );
};

export default GanttChart;

This code displays an empty Gantt chart without any configuration. Let’s display a task:

import React from 'react';
import {DayPilotGantt} from "daypilot-pro-react";

const GanttChart = () => {
  return (
    <div>
      <DayPilotGantt
        startDate={"2025-01-01"}
        days={30}
        tasks={[
          {
            "id": 1,
            "text": "Task 1",
            "start": "2025-01-04T00:00:00",
            "end": "2025-01-16T00:00:00",
          }
        ]}
      />
    </div>
  );
};

export default GanttChart;

Our application now displays a minimal Gantt chart with a single task:

React Gantt Chart Simple Configuration with One Task

The tasks are defined using the tasks={} attribute of the <DayPilotGantt> tag. 

The structure of the data object is defined in the API docs (see DayPilot.Task.data).

We define four basic properties: 

  • id - task ID

  • text - task name to be displayed in the Gantt chart

  • start - task start (DayPilot.Date object or ISO 8601 date/time string)

  • end - task start (DayPilot.Date object or ISO 8601 date/time string)

These properties define the task identity and position - they are required to display the task in the Gantt chart.

Each task will be displayed in a separate row. The task names (and possibly additional properties) are displayed in the row headers on the left side. The task date/time position is displayed in the time grid as well. If you need to display multiple tasks in the same row, you can check the React Scheduler component, which allows greater flexibility in the task display.

The startDate and days properties define the grid start and end. In our example, we display 31 days - starting on January 1, 2025.

Let's add another task now and a link that highlights the dependency between them:

import React from 'react';
import {DayPilotGantt} from "daypilot-pro-react";

const GanttChart = () => {
  return (
    <div>
      <DayPilotGantt
        startDate={"2025-01-01"}
        days={30}
        tasks={[
            {
              id: 1,
              text: "Task 1",
              start: "2025-01-04T00:00:00",
              end: "2025-01-10T00:00:00",
            },
            {
              id: 2,
              text: "Task 2",
              start: "2025-01-10T00:00:00",
              end: "2025-01-16T00:00:00",
            }
        ]}
        links={[
          {
            from: 1,
            to: 2,
            type: "FinishToStart"
          }
        ]}
      />
    </div>
  );
};

export default GanttChart;

And the result:

React Gantt Chart with Tasks and Dependency Links

Gantt Chart Configuration

In the previous examples, we have defined the Gantt chart properties directly using the component attributes.

In this step, we will move the dynamic properties to state variables:(startDate, days, tasks, and links).

The static configuration properties will be moved to a special config object. The properties defined in the config object will be applied to the Gantt chart component using the spread syntax (...config).

We will also add a complete property to our task records (it sets the task progress bar value) and add a milestone record (type: "Milestone").

import React, { useState, useEffect } from 'react';
import { DayPilotGantt } from "daypilot-pro-react";

const GanttChart = () => {
  const [gantt, setGantt] = useState(null);
  const [startDate, setStartDate] = useState("2025-01-01");
  const [days, setDays] = useState(30);
  const [tasks, setTasks] = useState([]);
  const [links, setLinks] = useState([]);

  const config = {
    timeHeaders: [
      { groupBy: "Month" },
      { groupBy: "Day", format: "d" }
    ],
    scale: "Day"
  };

  useEffect(() => {
    const tasks = [
      {
        id: 1,
        text: "Task 1",
        start: "2025-01-04T00:00:00",
        end: "2025-01-10T00:00:00",
        complete: 50
      },
      {
        id: 2,
        text: "Task 2",
        start: "2025-01-10T00:00:00",
        end: "2025-01-16T00:00:00",
        complete: 60
      },
      {
        id: 3,
        text: "Milestone 3",
        type: "Milestone",
        start: "2025-01-16T00:00:00",
        end: "2025-01-16T00:00:00"
      }
    ];
    setTasks(tasks);

    const links = [
      {
        from: 1,
        to: 2,
        type: "FinishToStart"
      }
    ];
    setLinks(links);
  }, [gantt]);

  return (
    <div>
      <DayPilotGantt
        {...config}
        startDate={startDate}
        days={days}
        tasks={tasks}
        links={links}
        controlRef={setGantt}
      />
    </div>
  );
};

export default GanttChart;

Our updated Gantt chart with progress bars and a milestone:

Simple React Gantt Chart Component with Tasks, Links and Milestones

Row Header Columns with Additional Task Data

React Gantt Chart with Additional Columns

In this step, we will customize the row headers of the Gantt chart component to display some more columns in addition to the task name:

  • Progress

  • Duration

The row header columns can be defined using the columns property:

const config = {
  columns: [
    {name: "Name", property: "text"},
    {name: "Complete"},
    {name: "Duration"},
  ],  
  // ...
};

The name property specifies the column name that will be displayed in the title. The property value specifies the property of the task that will be used for cell content in each row.

The “Complete” and “Duration” columns will require additional formatting, so we don’t specify the property for them. Instead, we will use the onBeforeRowHeaderRender to define the cell content:

const config = {
  // ...
  onBeforeRowHeaderRender: (args) => {
    if (args.task.type() !== "Milestone") {
      args.row.columns[1].html = args.task.data.complete + "%";
      args.row.columns[2].html = args.task.duration().totalDays() + " days";
    }
  },
  // ...
};

You can use this feature to display additional task details in the Gantt chart, such as ID, task owner, priority, and so on.

Full Source Code

Here is the full source code of our React Gantt Chart component:

import React, { useEffect, useRef, useState } from 'react';
import { DayPilot, DayPilotGantt } from "daypilot-pro-react";

const Gantt = () => {
  const [gantt, setGantt] = useState(null);
  const [tasks, setTasks] = useState([]);
  const [links, setLinks] = useState([]);
  const config = {
    timeHeaders: [{groupBy: "Month"},{groupBy: "Day", format:"d"}],
    scale: "Day",
    days: 90,
    startDate: "2025-01-01",
    taskHeight: 35,
    heightSpec: "Max",
    height: 600,
    rowHeaderHideIconEnabled: false,
    columns: [
      {name: "Name", property: "text"},
      {name: "Complete"},
      {name: "Duration"},
    ],
    onBeforeRowHeaderRender: (args) => {
      console.log("onBeforeRowHeaderRender", args);
      if (args.task.type() !== "Milestone") {
        args.row.columns[1].html = args.task.data.complete + "%";
        args.row.columns[2].html = args.task.duration().totalDays() + " days";
      }
    },
    rowMoveHandling: "Update",
    onRowMoved: (args) => {
      args.control.message("Row moved: " + args.source.text());
    },
    taskMoveHandling: "Update",
    onTaskMoved: (args) => {
      args.control.message("Task moved to: " + args.newStart);
    },
    linkCreateHandling: "Update",
    onLinkCreated: (args) => {
      args.control.message("Link created, type: " + args.type);
    },
    rowCreateHandling: "Enabled",
    onRowCreate: (args) => {
      args.control.tasks.add({
        id: DayPilot.guid(),
        text: args.text,
        start: args.control.startDate,
        end: args.control.startDate.addDays(1)
      });
    },
  };

  useEffect(() => {

    const tasks = [
      {
        id: 101,
        text: "Group 101",
        complete: 35,
        children: [
          {
            id: 102,
            start: "2025-01-02T00:00:00",
            end: "2025-01-04T00:00:00",
            text: "Task 1",
            complete: 60
          },
          {
            id: 103,
            start: "2025-01-05T00:00:00",
            end: "2025-01-08T00:00:00",
            text: "Task 2",
            complete: 0
          },
          {
            id: 104,
            start: "2025-01-08T00:00:00",
            type: "Milestone",
            text: "Milestone 1",
          }
        ],
      },
      {
        id: 201,
        text: "Group 201",
        complete: 35,
        children: [
          {
            id: 202,
            start: "2025-01-08T00:00:00",
            end: "2025-01-11T00:00:00",
            text: "Task 202",
            complete: 60
          },
          {
            id: 203,
            start: "2025-01-11T00:00:00",
            end: "2025-01-13T00:00:00",
            text: "Task 203",
            complete: 0
          },
          {
            id: 204,
            start: "2025-01-13T00:00:00",
            type: "Milestone",
            text: "Milestone 204",
          }
        ],
      }
    ];
    setTasks(tasks);


    const links = [
      { from: 102, to: 103, type: "FinishToStart"},
      { from: 202, to: 203, type: "FinishToStart"},
      { from: 101, to: 201, type: "FinishToStart"},
    ];
    setLinks(links);

  }, [gantt]);

  return (
    <div>
      <DayPilotGantt
        {...config}
        tasks={tasks}
        links={links}
        controlRef={setGantt}
      />
    </div>
  );
}
export default Gantt;

History

  • July 23, 2024: Upgraded to React 18, DayPilot Pro 2024.3.5972, row header columns added.

  • December 5, 2020: Upgraded to DayPilot Pro for JavaScript 2020.4.4788, React 17.

  • October 3, 2019: Initial release, React 16.