Docs

Documentation versions (currently viewingVaadin 24)

Gantt Chart

Vaadin Charts support for creating Gantt charts.

A Gantt chart is a type of bar chart that can represent a project schedule. It’s used for planning and scheduling projects, for displaying the start and finish dates of a project’s various elements. It can help in visualizing a project’s timeline, task dependencies, and progress.

Typical Use Case

A typical use case for a Gantt chart is in managing a project. For example, a project manager can use a Gantt chart to do the following:

  • Plan a project timeline by listing all tasks along with their start and end dates;

  • Identify task dependencies to understand which tasks need to be completed before others can start;

  • Track the progress of tasks to ensure the project is on schedule; and

  • Allocate resources by assigning tasks to team members and ensuring workload is balanced.

Gantt charts are particularly useful for complex projects with multiple tasks and dependencies, such as software development, construction projects, and event planning.

Adding Gantt Chart to Code

You can add Gantt chart to your application by performing the following steps:

  • Specify the chart type with ChartType.GANTT;

  • Create GanttSeries with GanttSeriesItems to represent the tasks; and

  • Then add the series to the chart.

You can alternatively configure the chart using options in the PlotOptionsGantt configuration object.

Open in a
new tab
Chart chart = new Chart(ChartType.GANTT);

final Configuration configuration = chart.getConfiguration();

configuration.setTitle("Gantt Chart");

XAxis xAxis = configuration.getxAxis();
xAxis.setMin(Instant.parse("2014-10-17T00:00:00Z"));
xAxis.setMax(Instant.parse("2014-10-30T00:00:00Z"));

PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
configuration.setPlotOptions(plotOptionsGantt);

GanttSeries series = new GanttSeries();
series.add(new GanttSeriesItem("Start prototype",
        Instant.parse("2014-10-18T00:00:00Z"),
        Instant.parse("2014-10-25T00:00:00Z")));

series.add(new GanttSeriesItem("Test prototype",
        Instant.parse("2014-10-27T00:00:00Z"),
        Instant.parse("2014-10-29T00:00:00Z")));

series.add(new GanttSeriesItem("Develop",
        Instant.parse("2014-10-20T00:00:00Z"),
        Instant.parse("2014-10-25T00:00:00Z")));

series.add(new GanttSeriesItem("Run acceptance tests",
        Instant.parse("2014-10-23T00:00:00Z"),
        Instant.parse("2014-10-26T00:00:00Z")));

configuration.addSeries(series);

Gantt Data Series

The GanttSeries class is used to represent tasks in a Gantt chart. Each task is represented by a GanttSeriesItem, which includes properties such as the task name, start time, end time, completion status or dependencies of other tasks.

Chart chart = new Chart(ChartType.GANTT);

final Configuration configuration = chart.getConfiguration();

PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
configuration.setPlotOptions(plotOptionsGantt);

GanttSeries series = new GanttSeries();

series.add(new GanttSeriesItem("Start prototype",
Instant.parse("2014-10-18T00:00:00Z"),
Instant.parse("2014-10-25T00:00:00Z")));

series.add(new GanttSeriesItem("Test prototype",
Instant.parse("2014-10-27T00:00:00Z"),
Instant.parse("2014-10-29T00:00:00Z")));

series.add(new GanttSeriesItem("Develop",
Instant.parse("2014-10-20T00:00:00Z"),
Instant.parse("2014-10-25T00:00:00Z")));

series.add(new GanttSeriesItem("Run acceptance tests",
Instant.parse("2014-10-23T00:00:00Z"),
Instant.parse("2014-10-26T00:00:00Z")));

configuration.addSeries(series);

Chart Configuration

The chart configuration involves several aspects, including horizontal and vertical axis configuration. It also includes grouping and custom labeling tasks, and setting row heights and other properties.

Horizontal Axis Configuration

The default settings for Gantt renders a dual date-time horizontal axis on the top of the chart. The tickInterval for the bottom horizontal axis is determined by the distribution of the series data points and available screen size. Respectively, the top axis is then assigned a higher date time interval (e.g., days-week, weeks-months, months-years). This logic is helpful when displaying Gantt charts on different devices. The Gantt chart automatically adapts and finds the right distribution of axis ticks based upon the screen size available.

If the minimum and maximum width of the chart is set, there’s more control over the number of ticks displayed in the Gantt chart. This allows for further customization of the labels and tickInterval properties on the axis.

The horizontal axis can be further configured to display less or more of the "date-time rows". See the following example to understand better how the horizontal axis can be configured:

Open in a
new tab
private void configureYearsMonthsWeeksOnXAxis(Configuration configuration) {
    configureWeeksAxis(configuration);
    configureMonthsAxis(configuration);
    configureYearsAxis(configuration);
}

private void configureWeeksAxis(Configuration configuration) {
    XAxis axis = new XAxis();
    configuration.addxAxis(axis);

    axis.setMinPadding(0.02);
    axis.setMaxPadding(0.02);
    axis.setUnits(new TimeUnitMultiples(TimeUnit.WEEK, 1));

    final Labels labels = new Labels();
    labels.setPadding(1);
    labels.setAlign(HorizontalAlign.LEFT);
    var style = new Style();
    style.setFontSize("8px");
    labels.setStyle(style);
    axis.setLabels(labels);

    axis.setGrid(new AxisGrid());
    axis.getGrid().setCellHeight(20);
}

Vertical Axis Configuration

If not specified, the Gantt chart determines the vertical axis rows, based on the unique names of the tasks in the data series, as specified by the setName(String) method in the GanttSeriesItem class. This means that each unique task name corresponds to a separate row in the chart.

For an example of such configuration, see the Gantt chart example in the Adding Gantt Chart to Code.

Group Tasks Vertically

For grouping tasks in a Gantt chart on horizontal tracks, use a vertical category axis. This type of Gantt chart is often used to display resource allocation, or availability schedules.

The chart rows (i.e., tracks) can be configured by specifying categories in the YAxis configuration. Each GanttSeriesItem then references the appropriate category using the setY(Number) method, where y is the ordinal number of the category.

Open in a
new tab
var rentalData = getRentalData();

YAxis yAxis = configuration.getyAxis();
yAxis.setType(AxisType.CATEGORY);
rentalData.forEach(car -> yAxis.addCategory(car.model));

for (int i = 0; i < rentalData.size(); i++) {
    CarRental car = rentalData.get(i);
    GanttSeries series = new GanttSeries();
    series.setName(car.model);
    for (CarRentalDeal deal : car.deals) {
        GanttSeriesItem item = new GanttSeriesItem(i, deal.from,
                deal.to);
        item.setId("deal-" + i);
        series.add(item);
    }
    configuration.addSeries(series);
}

Grouping Tasks in a Hierarchy

You can split larger tasks into sub-tasks, or group resources together if they belong to the same parent task. To establish the parent-child relationship between two tasks, use the GanttSeriesItem#setParent(String) method.

When making such a relationship, use the setParent(String) method on the child task to pass it the parent task’s ID. You can get that by first calling getId(). Here’s an example of how you might do this:

var parentId = parentItem.getId();
childItem.setParent(parentId);

The duration of the parent task spans all sub-tasks. For a detailed example of such a configuration, see the section A Complete Task Dependencies Example

Configure Row Height

You can affect the height of the rows in a Gantt chart in multiple ways. Below is a list of them:

Set Overall Height of Chart

By setting the height of the chart, you can indirectly control the height of the rows. A taller chart results in taller rows, while a narrower chart results in more narrow rows.

Chart chart = new Chart(ChartType.GANTT);
chart.getConfiguration().getChart().setHeight("700px");

Using YAxis.setStaticScale

The YAxis.setStaticScale() method allows you to set a fixed height for each row in the Gantt chart. This method takes a double value, representing the height of each row in pixels. For example, setting the static scale to 24 results in each Y axis category using 24 pixels, and the height of the chart adjusts accordingly. Adding or removing categories resizes the chart.

Chart chart = new Chart(ChartType.GANTT);
final Configuration configuration = chart.getConfiguration();
YAxis yAxis = configuration.getyAxis();
yAxis.setStaticScale(24);

Configuring Data Point in PlotOptionsGantt

You can also affect the height of the rows by using the PlotOptionsGantt#setPointWidth() method. This configuration sets the width of the task bar. In Gantt charts, making the bar wider indirectly affects the overall row height. Below is an example of that:

Chart chart = new Chart(ChartType.GANTT);
final Configuration configuration = chart.getConfiguration();
PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
plotOptionsGantt.setPointWidth(30);
configuration.setPlotOptions(plotOptionsGantt);

Task Custom Labels

The PlotOptionsGantt#setDataLabels() method allows you to display one or more labels for each task in the Gantt chart. These labels can provide additional information about the tasks, such as assignee, start date, end date, and custom data.

For each label, you can configure alignment relative to the task, format, color, border and many other style options (see DataLabels class for a complete list of options). The DataLabels class allows you to format labels to display either a simple value or HTML code. This flexibility permits you to customize the appearance and the content of the labels in a chart.

Open in a
new tab
final GanttSeries projectDevelopmentSeries = createProjectDevelopmentSeries();
PlotOptionsGantt seriesPlotOptions = new PlotOptionsGantt();
var dataLabels = new ArrayList<DataLabels>();

var assigneeLabel = new DataLabels(true);
assigneeLabel.setAlign(HorizontalAlign.LEFT);
assigneeLabel.setFormat("{point.custom.assignee}");
dataLabels.add(assigneeLabel);

var endDateLabel = new DataLabels(true);
endDateLabel.setAlign(HorizontalAlign.RIGHT);
endDateLabel.setFormat("{point.end:%e. %b}");
dataLabels.add(endDateLabel);

var avatarLabel = new DataLabels(true);
avatarLabel.setAlign(HorizontalAlign.LEFT);
avatarLabel.setUseHTML(true);
avatarLabel.setFormat(
        "<div style=\"width: 20px; height: 20px; overflow: hidden; margin-left: -30px\">"
                + "                <img src=\"https://ui-avatars.com/api/?background=random&color=fff&size=20&length=1&rounded=true&name={point.custom.assignee}\"> "
                + "                </div>");
dataLabels.add(avatarLabel);

seriesPlotOptions.setDataLabels(dataLabels);
projectDevelopmentSeries.setPlotOptions(seriesPlotOptions);

Tooltips

In addition to task labels, you can also activate tooltips. They’re shown by a chart task when hovering over it. You can customize the appearance of the tooltip, as well as its content, using the Tooltip class, passed to the chart configuration:

Configuration configuration = chart.getConfiguration();
Tooltip tooltip = new Tooltip(true);
tooltip.setOutside(true);
tooltip.setShadow(true);
tooltip.setUseHTML(true);
tooltip.setPointFormat("<span><b>{point.name}</b></span>");
configuration.setTooltip(tooltip);

Custom Data in Tasks

The GanttSeries and GanttSeriesItem classes allow you to assign custom data to each item using the GanttSeriesItem#setCustom() method. This can be used to render labels and tooltips, or access the data in callbacks — such as when a task is clicked.

The custom data assigned to a GanttSeriesItem must be a subclass of AbstractConfigurationObject to ensure that it can be serialized to JSON. This is necessary for the data to be properly transmitted and rendered in the Gantt chart.

You can access the custom data when formatting labels under a {point.custom.*} object. For example, when you store an object having an assignee property via the GanttSeriesItem#setCustom() method, you can access this data in the label formatter like so:

var assigneeLabel = new DataLabels(true);
assigneeLabel.setFormat("{point.custom.assignee}");

To access the custom data in the click event listeners, use the following code:

// Configure click callback
chart.addPointClickListener(event -> {
    var ganttSeries = ((GanttSeries) event.getSeries());
    var customData = (TaskCustomData) ganttSeries
                        .get(event.getItemIndex())
                        .getCustom();
    System.out.println("Task assigned to " + customData.assignee);
});
Open in a
new tab
// Create series with custom data
GanttSeries series = new GanttSeries();
GanttSeriesItem item;

item = new GanttSeriesItem(0, todayPlus(1), todayPlus(3));
item.setCustom(new TaskCustomData("Aria Bailey"));
series.add(item);

item = new GanttSeriesItem(1, todayPlus(2), todayPlus(5));
item.setCustom(new TaskCustomData("Eleanor Price"));

series.add(item);

Task Progress Indication

The completed property of a GanttSeriesItem is used to indicate the progress of a task in a Gantt chart. This property can be set to a value between 0 and 1, representing the percentage of the task that has been completed. For example, to indicate that the task is 45% completed, configure the GanttSeriesItem by calling setCompleted(0.45).

GanttSeriesItem task = new GanttSeriesItem();
task.setCompleted(0.5); // 50% completed

Optionally, you can use GanttSeriesItem#setCompleted(Completed) method for a more fine-grained customization of the progress, such as specifying the color of the progress indicator.

GanttSeriesItem task = new GanttSeriesItem();
Completed completed = new Completed();
completed.setAmount(0.5); // 50% completed
completed.setFill(SolidColor.GREEN); // Custom color for the progress indicator
task.setCompleted(completed);

The following example shows the complete example of Gantt chart with progress indication:

Open in a
new tab
GanttSeries series = new GanttSeries();
series.setName("Project 1");
final GanttSeriesItem startPrototype = new GanttSeriesItem(
        "Start prototype", Instant.parse("2014-10-18T00:00:00Z"),
        Instant.parse("2014-10-25T00:00:00Z"));
startPrototype.setCompleted(0.25);
series.add(startPrototype);

series.add(new GanttSeriesItem("Test prototype",
        Instant.parse("2014-10-27T00:00:00Z"),
        Instant.parse("2014-10-29T00:00:00Z")));

final GanttSeriesItem develop = new GanttSeriesItem("Develop",
        Instant.parse("2014-10-20T00:00:00Z"),
        Instant.parse("2014-10-25T00:00:00Z"));
develop.setCompleted(new Completed(0.12, SolidColor.ORANGE));
series.add(develop);

series.add(new GanttSeriesItem("Run acceptance tests",
        Instant.parse("2014-10-23T00:00:00Z"),
        Instant.parse("2014-10-26T00:00:00Z")));

configuration.addSeries(series);

Task Dependencies

The dependency property of a GanttSeriesItem allows you to define dependencies between tasks in a Gantt chart. By specifying dependencies, you can indicate that a task cannot start until another task is completed.

Below is a list of typical scenarios:

  • Sequential Tasks: One task must be completed before another can start, such as completing a prototype before testing it.

  • Milestones: Define key points in the project that depend on the completion of multiple preceding tasks.

  • Parallel Tasks: Managing tasks that can run in parallel, but have dependencies on other tasks.

Configure Dependencies Between Points

To specify dependencies between tasks in a Gantt chart, you must set a unique ID for each GanttSeriesItem. This ID is used to reference the task when defining dependencies.

GanttSeriesItem task1 = new GanttSeriesItem(...);
task1.setId("task1");

GanttSeriesItem task2 = new GanttSeriesItem(...);
task2.setId("task2");

// Task 2 depends on completion of Task 1
task2.addDependency(task1.getId());

In this example, task2 is dependent on the completion of task1. This ensures that task2 cannot start until task1 is finished. This dependency is visually represented in the Gantt chart, providing a clear indication of the task sequence:

Open in a
new tab
GanttSeries series = new GanttSeries();

GanttSeriesItem task1 = new GanttSeriesItem("task1", todayPlus(1),
        todayPlus(2));
task1.setId("task1");

GanttSeriesItem task2 = new GanttSeriesItem("task2", todayPlus(4),
        todayPlus(8));
task2.setId("task2");

task2.addDependency(task1.getId());

series.addAll(task1, task2);
configuration.addSeries(series);

Connector Styles

A connector is a line that visually represents the dependency between two tasks in a Gantt chart. It consists of a line, a start marker, and an end marker. You can configure the style of the line, it’s color and width. Start and end markers define how the line is started and ended. By default, the markers are configured in a way that the connectors look like an arrow. This can be changed by the Marker configuration.

Gantt task dependencies can be visually configured at different levels in a Gantt chart. This allows for flexible and detailed customization of how dependencies are displayed.

Chart Level Configuration

At the chart level, you can configure connectors using the ChartConnectors class. This configuration applies to all dependencies within the chart.

ChartConnectors connectors = new ChartConnectors();
// Set the dash style for all connectors in the chart
connectors.setDashStyle(DashStyle.SHORTDASH);
configuration.setConnectors(connectors);

Series Level Configuration

At the series level, you can configure connectors using the SeriesConnectors class. This allows you to apply specific styles to all dependencies within a particular series.

PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
SeriesConnectors seriesConnectors = new SeriesConnectors();
// Set the dash style for all connectors in the series
seriesConnectors.setDashStyle(DashStyle.DOT);
plotOptionsGantt.setConnectors(seriesConnectors);
series.setPlotOptions(plotOptionsGantt);

Dependency Level Configuration

At the dependency level, you can configure connectors using the GanttSeriesItemDependency class. This provides the most granular level of customization, allowing you to specify styles for individual dependencies.

GanttSeriesItemDependency dependency = new GanttSeriesItemDependency("task1");
// Set the dash style for this specific dependency.
dependency.setDashStyle(DashStyle.SOLID);
item.addDependency(dependency);

A Complete Task Dependencies Example

The following shows a full example of specific dependencies between tasks, as well as adding multiple series to a single Gantt chart:

Open in a
new tab
Chart chart = new Chart(ChartType.GANTT);

        final Configuration configuration = chart.getConfiguration();
        configuration.setTitle("Gantt Project Management");
        ChartConnectors connectors = new ChartConnectors();
        connectors.setDashStyle(DashStyle.SHORTDASH);
        configuration.setConnectors(connectors);

        Tooltip tooltip = new Tooltip();
        tooltip.setPointFormat(
                "<span><b>{point.name}</b></span><br/><span>Start: {point.start:%e. %b}</span><br/><span>End: {point.end:%e. %b}</span><br/><span>Owner: {point.custom.owner}</span>");
        configuration.setTooltip(tooltip);

        XAxis xAxis = configuration.getxAxis();
        PlotLine dateIndicator = new PlotLine();
        dateIndicator.setDashStyle(DashStyle.DASH);
        xAxis.setCurrentDateIndicator(dateIndicator);
        xAxis.setMin(todayPlus(-3));
        xAxis.setMax(todayPlus(18));

        PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
        configuration.setPlotOptions(plotOptionsGantt);

        configuration.addSeries(createOfficesSeries());
        configuration.addSeries(createNewProductLaunchSeries());


        chart.addPointClickListener(event -> {
            var name = ((GanttSeries) event.getSeries())
                    .get(event.getItemIndex()).getName();
            System.out.println("Clicked on " + name);
        });

        add(chart);
    }

    private GanttSeries createNewProductLaunchSeries() {
        GanttSeries series = new GanttSeries();
        series.setName("Product");

        GanttSeriesItem item;

        item = new GanttSeriesItem();
        item.setName("New product launch");
        item.setId("new_product");
        item.setCustom(new TaskCustomData("Peter"));
        series.add(item);

        item = new GanttSeriesItem("Development", todayPlus(-1), todayPlus(11));
        item.setId("development");
        item.setCompleted(new Completed(0.6, SolidColor.ORANGE));
        item.setCustom(new TaskCustomData("Susan"));
        item.setParent("new_product");
        series.add(item);

        item = new GanttSeriesItem();
        item.setName("Beta");
        item.setStart(todayPlus(12));
        item.setId("beta");
        item.addDependency(new GanttSeriesItemDependency("development"));
        item.setMilestone(true);
        item.setCustom(new TaskCustomData("Peter"));
        item.setParent("new_product");
        series.add(item);

        item = new GanttSeriesItem("Final development", todayPlus(13),
                todayPlus(17));
        item.setId("finalize");
        item.addDependency(new GanttSeriesItemDependency("beta"));
        item.setParent("new_product");
        series.add(item);

        item = new GanttSeriesItem();
        item.setName("Launch");
        item.setStart(todayPlus(17).plus(12, ChronoUnit.HOURS));
        item.addDependency(new GanttSeriesItemDependency("finalize"));
        item.setMilestone(true);
        item.setCustom(new TaskCustomData("Peter"));
        item.setParent("new_product");
        series.add(item);

        return series;
    }

    private GanttSeries createOfficesSeries() {
        GanttSeries series = new GanttSeries();
        series.setName("Offices");

        GanttSeriesItem item;

        item = new GanttSeriesItem();
        item.setName("New offices");
        item.setId("new_offices");
        item.setCustom(new TaskCustomData("Peter"));
        series.add(item);

        item = new GanttSeriesItem("Prepare office building", todayPlus(-2),
                todayPlus(6));
        item.setId("prepare_building");
        item.setCustom(new TaskCustomData("Linda"));
        item.setCompleted(0.2);
        item.setParent("new_offices");
        series.add(item);

        item = new GanttSeriesItem("Inspect building", todayPlus(4),
                todayPlus(8));
        item.setId("inspect_building");
        item.setParent("new_offices");
        item.setCustom(new TaskCustomData("Ivy"));
        series.add(item);

        item = new GanttSeriesItem("Passed inspection", todayPlus(9),
                todayPlus(9));
        item.setId("passed_inspection");
        item.addDependency("prepare_building");
        item.addDependency("inspect_building");
        item.setParent("new_offices");
        item.setMilestone(true);
        item.setCustom(new TaskCustomData("Peter"));
        series.add(item);

        item = new GanttSeriesItem();
        item.setName("Relocate");
        item.setId("relocate");
        item.addDependency(new GanttSeriesItemDependency("passed_inspection"));
        item.setParent("new_offices");
        item.setCustom(new TaskCustomData("Josh"));
        series.add(item);

        item = new GanttSeriesItem("Relocate staff", todayPlus(10),
                todayPlus(11));
        item.setId("relocate_staff");
        item.setParent("relocate");
        item.setCustom(new TaskCustomData("Mark"));
        series.add(item);

        item = new GanttSeriesItem("Relocate test facility", todayPlus(11),
                todayPlus(13));
        item.setId("relocate_test_facility");
        item.addDependency(new GanttSeriesItemDependency("relocate_staff"));
        item.setParent("relocate");
        item.setCustom(new TaskCustomData("Anne"));
        series.add(item);

        item = new GanttSeriesItem("Relocate cantina", todayPlus(11),
                todayPlus(14));
        item.setId("relocate_cantina");
        final GanttSeriesItemDependency relocateStaff = new GanttSeriesItemDependency(
                "relocate_staff");
        relocateStaff.setDashStyle(DashStyle.SOLID);
        item.addDependency(relocateStaff);
        item.setParent("relocate");
        series.add(item);

        return series;
    }

    private Instant todayPlus(int days) {
        return TODAY.plus(days, ChronoUnit.DAYS);
    }

    @SuppressWarnings("unused")
    static class TaskCustomData extends AbstractConfigurationObject {
        private String owner;

        public TaskCustomData(String owner) {
            this.owner = owner;
        }

        public String getOwner() {
            return owner;
        }

        public void setOwner(String owner) {
            this.owner = owner;
        }
    }

}

Indication of Current Date

The currentDateIndicator property of the XAxis class allows you to display the current date on a Gantt chart. This is useful for highlighting the current date within the timeline of a chart, providing a visual reference point for the current progress of tasks.

You can enable the current date indicator using xAxis.setCurrentDateIndicator(true), or further customize the indicator appearance by using xAxis.setCurrentDateIndicator(PlotLine) method.

Open in a
new tab
Chart chart = new Chart(ChartType.GANTT);

final Configuration configuration = chart.getConfiguration();

final XAxis xAxis = configuration.getxAxis();
xAxis.setCurrentDateIndicator(true);

Even in a Gantt chart, you can display the timeline with a navigator and time-range selector to allow users to navigate easily through the project timeline. Activate this feature by enabling Scrollbar, RangeSelector, and Navigator like so:

Chart chart = new Chart(ChartType.GANTT);
final Configuration configuration = chart.getConfiguration();
configuration.getScrollbar().setEnabled(true);
configuration.getRangeSelector().setEnabled(true);
configuration.getNavigator().setEnabled(true);

You can configure the Navigator and RangeSelector classes in the same way as in the Timeline feature. Use PlotOptionsGantt and YAxis configuration to further customize the Navigator appearance, as in the example below:

Open in a
new tab
final Navigator navigator = configuration.getNavigator();
navigator.setEnabled(true);
final YAxis navigatorYAxis = navigator.getYAxis();
navigatorYAxis.setMin(0);
navigatorYAxis.setMax(3);
navigatorYAxis.setReversed(true);
navigatorYAxis.setCategories();

configuration.getScrollbar().setEnabled(true);

configuration.getRangeSelector().setEnabled(true);
configuration.getRangeSelector().setSelected(0);

Left Axis as a Grid

In a Gantt chart, it’s common to display a table on the left side of the chart to show task information (e.g., task name, assignee, and duration). The tasks are aligned and mapped to the table after setting the GanttSeriesItem.setY(Number) value for each data point (task).

Grid Column Configuration

The AxisGrid class allows you to configure the grid of a Gantt chart, so that you may display additional columns of information alongside the task names. This can be useful for providing more context and details about each task.

AxisGrid grid = new AxisGrid();
grid.setEnabled(true);
grid.setColumns(List.of(
    createProjectColumn(),
    createEstDaysColumn(),
    createStartDateColumn(),
    createEndDateColumn()
));
chart.configuration().getyAxis().setGrid(grid);

In this example, the AxisGrid is enabled and configured with multiple columns, each created by a helper method. These columns display various details such as project name, estimated days, start date, and end date.

The following is an example of a helper method for the Project name column. The other helper methods look very similar. For details, see the complete chart example further below.

private XAxis createProjectColumn() {
    XAxis column = new XAxis();
    column.setTitle("Project");
    Labels label = new Labels();
    label.setFormat("{point.name}");
    column.setLabels(label);
    return column;
}

In the example above, you can see that the grid cell value is computed from the {point.name} value of the task. You can also use more complicated formatting functions, even performing a computation in them and returning a HTML code, instead of a simple value:

private XAxis createEstDaysColumn() {
    XAxis column = new XAxis();
    column.setTitle("Est. Days");
    final Labels label = new Labels();
    label.setUseHTML(true);
    label.setFormatter(
            "function () { var point = this.point,days = (1000 * 60 * 60 * 24)," +
            "    number = (point.x2 - point.x) / days; " +
            "    return '<div style=\"width: 50px; text-align: center\">' + Math.round(number * 100) / 100 + '</div>';" +
            "}");
    column.setLabels(label);
    return column;
}

A Complete Grid Example

Open in a
new tab
public GanttYAxisAsGridDemo() {
    Chart chart = new Chart(ChartType.GANTT);

    final Configuration configuration = chart.getConfiguration();
    configuration.setTitle("Gantt Chart Grid Demo");

    XAxis xAxis = configuration.getxAxis();
    xAxis.setTickPixelInterval(70);

    YAxis yAxis = configuration.getyAxis();
    yAxis.setType(AxisType.CATEGORY);

    AxisGrid grid = new AxisGrid();
    grid.setEnabled(true);
    grid.setColumns(List.of(
            createProjectColumn(),
            createEstDaysColumn(),
            createStartDateColumn(),
            createEndDateColumn())
    );
    yAxis.setGrid(grid);

    PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
    configuration.setPlotOptions(plotOptionsGantt);

    final GanttSeries projectDevelopmentSeries = createProjectDevelopmentSeries();
    PlotOptionsGantt seriesPlotOptions = new PlotOptionsGantt();
    projectDevelopmentSeries.setPlotOptions(seriesPlotOptions);
    configuration.addSeries(projectDevelopmentSeries);

    add(chart);
}

private XAxis createProjectColumn() {
    XAxis column = new XAxis();
    column.setTitle("Project1");
    final Labels label = new Labels();
    label.setFormat("{point.name}");
    column.setLabels(label);
    return column;
}

Drag & Drop Support

You can add drag and drop support to the chart using the dragDrop property in the PlotOptionsGantt class. This feature allows you to move points around, or directly modify them within the chart. You can specify which axes are draggable, and you can set constraints on dragging behavior using properties in the DragDrop class.

You can also attach the drag and drop listeners to the chart to handle events related to dragging.

Table 1. Available Drag&Drop listeners
Handler Method Comment

Chart#addPointDragStartListener

triggered when a drag operation starts on a point.

Chart#addPointDragListener

triggered continuously while a point is being dragged.

Chart#addPointDropListener

triggered when a point is dropped after a drag operation.

Every listener has an event parameter that contains data about the dragged object, such as the point ID, the start date of the point, the end date, and data about the series.

Open in a
new tab
PlotOptionsGantt plotOptionsGantt = new PlotOptionsGantt();
plotOptionsGantt.setAnimation(false); // Do not animate dependency connectors
final DragDrop dragDrop = plotOptionsGantt.getDragDrop();
dragDrop.setDraggableX(true);
dragDrop.setDraggableY(true);
dragDrop.setDragMinY(0);
dragDrop.setDragMaxY(2);
dragDrop.setDragPrecisionX(1000 * 60 * 60 * 8); // Snap to eight hours

plotOptionsGantt.setAllowPointSelect(true);
configuration.setPlotOptions(plotOptionsGantt);