Meet DHTMLX Gantt 8.0

Meet DHTMLX Gantt 8.0

Project management is one of the most challenging aspects of doing business in today’s technological world. For years, DHTMLX Gantt has been a reliable tool for building business web apps based on feature-packed Gantt charts. Last month, the DHTMLX presented the new version of their top product - DHTMLX Gantt 8.0.

In this article, you will learn about the main novelties included in this release.

New Design for Gantt Samples

As the number of samples in our package grows, navigating through them may become more challenging. That is why we fully reworked the design of Gantt samples to give you a better way to get acquainted with the feature set of our library.

Check the sample >

Check the sample >

Now you can quickly find the links to the methods, properties, and events used in a particular sample under the API reference tab. You can also view the source code by simply switching to the Source code tab without the need to open it in the new browser window. If you would like to share a certain sample with your team, you can simply copy the link to the sample under the Share tab. To open a sample on a new page, just click on the Open sample button.

Apart from that, sample pages are now fully responsive, so they work great on various mobile devices. For instance, it is not a problem to review the source code or open links to the documentation using a smartphone or a tablet.

Simplified Resource Management Configuration

Resource management is probably one of the most demanded functionalities of our Gantt component and we came up with a number of ideas on how to optimize your coding experience with it in v8.0.

First of all, we introduced the ability to load resources and resource assignments together with tasks and dependencies between them.

gantt.parse({
    tasks: [
        ...,
        {
            id: 5,
            text: "Interior office",
            type: "task",
            start_date: "03-04-2024 00:00",
            duration: 7,
            parent: "2",
            owner: [{
                resource_id: "6",
                value: 3,
                start_date: "03-04-2024 00:00",
                end_date: "05-04-2024 00:00",
            }]
        },
        ...
    ],
    links: [],
    resources: [
        {id: 6, text: "John", unit: "hours/day" },
        {id: 7, text: "Mike", unit: "hours/day" },
        {id: 8, text: "Anna", unit: "hours/day" },
        {id: 9, text: "Bill", unit: "hours/day" },
        {id: 10, text: "Floe", unit: "hours/day" }
    ]
});

If needed, you can also pass resource assignments into the method separately from tasks.

Now any changes in resources and their assignments in Gantt can be sent to the dataProcessor as separate entries with persistent IDs, thus simplifying the integration with the backend API.

gantt.config.resources = {
    dataprocessor_assignments: true,
    dataprocessor_resources: true,
};
gantt.createDataProcessor(function(entity, action, data, id){
    switch (entity) {
        case "task":
            break;
        case "link":
            break;
        case "resource":
            break;
        case "assignment":
            break;
    }
});

It is also possible to capture resource-related changes in the handler by switching to the custom routing mode in the dataProcessor or by using the function declaration.

As a result, Gantt resources can be uploaded and saved just like tasks and links.

In v8.0, you’ll also benefit from numerous adjustments in the resource view configuration.

Here we should mention that the datastore for resources is now created automatically during the initialization of the Gantt chart. To make extra changes in the resource store, you should apply the new gantt.config.resources option:

gantt.config.resources = {
    resource_store: {
        type: "treeDataStore",
        fetchTasks: true,
        initItem: function(item) {
            item.parent = item.parent || gantt.config.root_id;
            item[gantt.config.resource_property] = item.parent;
            item.open = true;
            return item;
        }
    },
}

But at the same time, it is still possible to create the resource datastore manually and use it by default.

Starting from v8.0, you have an opportunity to make resource assignments editable in the resource diagram via the following config:

gantt.config.resources = {
    editable_resource_diagram: true
};

And lastly, now you are able to specify the behavior for the resource control in the lightbox using the lightbox_resources function. By default, the resource control will be populated with data from the resource datastore.

More details on these important additions to our JavaScript Gantt are provided in the documentation.

Saving Tree Structure When Grouping Tasks (PRO)

Grouping tasks is a widely used feature of our Gantt that allows quickly arranging Gantt tasks in accordance with a specific attribute. For v8.0, our customers gave us a cue on how to make it even better. Before that, the tree structure of Gantt was not saved after grouping, i.e. tasks were shown in a flat list, causing some inconvenience for end-users. It is no longer the issue. Now after performing grouping manipulations, the Gantt tree structure remains visible, when parent and child tasks belong to the same group.

To help you activate this helpful feature via API, we added a new boolean save_tree_structure parameter to the gantt.groupBy method. All you have to do is to set the value of this parameter to true.

gantt.groupBy({
    groups: groups,
    relation_property: gantt.config.resource_property,
    group_id: "group_id",
    group_text: "text",
    delimiter: ", ",
    default_group_label: "No Material",
    save_tree_structure: true
});

Gantt 8.0 - saved tree structure after grouping

Check the sample >

In the image above, you can see the Gantt chart, where tasks are grouped by resources and the tree structure is saved.

Note that this feature is available only in the PRO edition of DHTMLX Gantt.

Empty State Screen for Gantt

Previously, when a Gantt chart built with DHTMLX did not contain any tasks, it would appear blank. This could be misconstrued by first-time users as a chart-loading issue or any other error, leading to confusion about what to do next. Therefore, one of the challenges faced by our clients was implementing a comprehensive empty state for Gantt.

To address this issue, we have introduced a new built-in Empty Screen feature in Gantt. It is fully configurable and can be displayed in either the Grid or the Timeline part of the chart. The main purpose of the Empty State Screen is to invite end-users to begin scheduling their activities when there is no data loaded into the Gantt chart. In the code, this feature is activated through the show_empty_state config.

gantt.config.show_empty_state = true;

Moreover, the ext object in Gantt API now also includes the emptyStateElement extension with a range of methods related to the “empty state”. For instance, using the getContainer() method, you can show the “empty state” in the Gantt timeline without any tasks instead of the grid i.e. change the container where the “empty state” will be applied:

gantt.ext.emptyStateElement.getContainer = function() {
    return gantt.$task_data.closest(".gantt_layout_content");
};

Gantt 8.0 - empty state

Check the sample >

There is also an opportunity to change the content displayed in the “empty state” message with the renderContent() method:

gantt.ext.emptyStateElement.renderContent = function(container) {
    return `<div class='gantt_empty_state'>
        <div class='gantt_empty_state_image'></div>
        <div class='gantt_empty_state_text'>
            <div class='gantt_empty_state_text_link'     data-empty-state-create-task>${gantt.locale.labels.empty_state_text_link}</div>
            <div class='gantt_empty_state_text_description'>${gantt.locale.labels.empty_state_text_description}</div>
        </div>
  </div>`;
};

To get acquainted with other new methods provided in the emptyStateElement extension, visit this documentation page.

Background Grid in Empty Gantt Timeline

Another request from our users is the ability to display the background grid of the Timeline even if there are no tasks present. With our new release, you can now extend the background grid below the last task row to fill the entire timeline, making it work very well with certain UI solutions. Additionally, this feature comes in handy when the application allows users to create new tasks by dragging and dropping them into an empty space of the chart.

To add the background grid to the timeline, you need the following setting:

gantt.config.timeline_placeholder = true;

If necessary, you can also highlight particular columns and cells in the background grid via the timeline_cell_class template:

gantt.templates.timeline_cell_class = function (task, date) {
    if (!gantt.isWorkTime({ date: date, task: task })) {
        return "weekend";
    }
};

As for background rows, a temporary task object will be added to the template as described in the documentation.

Check the sample >

The background grid will be shown in the timeline when Gantt has no data or when the rows with tasks don’t fill the whole timeline.

New Way of Enabling Gantt Export

Exporting is a significant feature of DHTMLX Gantt. Earlier you could start using it after including the export api.js file on the HTML page or by putting it in the configuration folder and importing it (when using JS frameworks and Node.js). In v8.0, we provide a more convenient way for enabling this functionality. Now you can set it to work with the plugins() method:

gantt.plugins({
   export_api: true
})

Learn more about this novelty in the migration notes.

Inheriting Constraints from Projects (PRO)

When using the automatic scheduling feature in DHTMLX Gantt, end-users usually take the opportunity to add constraints for regular tasks to better fit their scheduling needs. It is also common to break complex tasks into multiple more manageable pieces. But in such cases setting restrictions on the start and/or finish dates of tasks will take more time.

The new version of the DHTMLX Gantt library eliminates this inconvenience by offering the possibility to inherit constraints of project-type tasks (or simply projects) in their child tasks. It means that you just have to set the desired type of constraint for the parent project, which will automatically apply to its children. At the same time, if any of the child tasks already has its own constraint, it won’t be replaced with the constraint of the parent task.

Check the sample >

Under the hood, this feature is enabled by changing the value of the newly added gantt.config.auto_scheduling_project_constraint property from false (default value) to true.

gantt.config.auto_scheduling_project_constraint = true;

Otherwise, constraints in projects won’t be applied to their nested tasks.

Note that this feature is available only in the PRO edition of DHTMLX Gantt.

Improved Calculation of Critical Path and Slack Times

Delivering projects on time is the primary purpose of using Gantt charts. But it frequently happens that due to any circumstances, project tasks require extra time to be completed. It may become a real headache for a project manager, because such time lags may affect the overall project deadline. In our Gantt, you can calculate slack times (free and total) and the critical path for Gantt tasks to be prepared for such emergencies. The new version includes several useful changes for these functionalities.

First of all, the calculation process of critical path and slack periods should become much faster for medium-sized projects. We also eliminated various issues related to slack calculations reported by our clients.

The new Gantt adds the possibility to calculate the total slack for projects. It will help end-users to get a general idea about the buffer time for completing tasks without affecting the deadline of the whole project. As a result, the total slack now can be calculated for all types of Gantt tasks, while the free slack is available only for regular tasks and milestones.

Starting from v8.0, the algorithms used in our Gantt for calculating the critical path, slack periods, and auto scheduling can also include values of task progress just like in MS Project.
It will help to tackle some issues related to completed tasks (100% progress) in the mentioned algorithms and ensure the following:

  • Completed tasks have zero slack

  • Completed tasks are not taken into account during the auto scheduling process

  • Completed tasks cannot be a part of the critical path in Gantt

This feature is disabled by default and the update won’t change the behavior of the calculation algorithms of Gantt in existing apps of our clients.

From the technical point of view, this novelty is enabled with the optional auto_scheduling_use_progress property:

gantt.config.auto_scheduling_use_progress = true;
gantt.init("gantt_here");

You can apply this config only when the critical path or auto scheduling extension is set to work via the corresponding plugin.

And bear in mind that the auto_scheduling_use_progress property is available only in the PRO edition of DHTMLX Gantt.

Updates for Split and Rollup Tasks

In DHTMLX Gantt, the abilities to split and roll up tasks are crucial for presenting project data in parent-child hierarchies or as summaries.

In v8.0, we give you more freedom in terms of customizing individual rollup and split tasks. The new Gantt enables you to apply various styles for the rollup and split task depending on their position in the timeline.

It is done using the task_class template enriched with the new task.$rendered_at property that indicates the id of the row, where a particular split task or a rollup item is rendered in the Gantt timeline:

gantt.templates.task_class = function(start, end, task) {
    if(task.$rendered_at) {
       if(gantt.calculateTaskLevel(gantt.getTask(task.$rendered_at)) === 1) {
               return "phase-level-split-task"; // or "phase-level-rollup";
       }
    }
    return " ";
};

Now you can control the visibility of each rollup task on its parent-project. It is implemented with the new onBeforeRollupTaskDisplay event.

We also added a filtering option for split tasks. To bring this useful task management feature into action, you’ll need to use the onBeforeSplitTaskDisplay event and return true or false for a specific subtask to be displayed or not in the Gantt chart accordingly.

gantt.attachEvent("onBeforeSplitTaskDisplay", function (id, task, parent) {
    if (task.progress === 1) {
        return false;
    }
        return true;
});

And the last thing we point out in this section, we have to mention that the rollup property of Gantt tasks with the project type now can get a false value. It will help to ensure that rollup elements won’t be rendered on a given project task. With all other values in the rollup property, rollup tasks will be rendered on projects as usual.

Server Confirmation for Deleted Tasks

When performing basic operations on tasks within the Gantt chart via the UI, it is necessary to be sure that these actions are saved properly on the server side and inform a user about it. For this purpose, DHTMLX utilizes the built-in DataProcessor library. But until recently, it has been limited to saving data changes associated with creating and editing tasks.

From now on, the DataProcessor object includes the new deleteAfterConfirmation: true setting option that will help in dealing with the deletion of tasks:

const dp = gantt.createDataProcessor({
    url: "/gantt/backend/data",
    mode: "REST",
    deleteAfterConfirmation: true
});

or

const dp = new gantt.dataProcessor("/api");
dp.init(gantt);
dp.setTransactionMode("REST");
dp.deleteAfterConfirmation = true;

Here is how it works in practice:

Gantt 8.0 - confirmation of a task deletion

Check the sample >

Just like with creating and editing, the task being deleted will be highlighted until receiving the response from the server with the operation completion confirmation. When the task is highlighted for too long, it may indicate something is wrong on the backend. If the task that you want to delete has dependencies or subtasks, their deletion will start only after the confirmation of the parent task removal.

New Approach to Adding Custom Content in Timeline Cells

Each project is unique in its own way and project managers may need to add some extra visual elements to the timeline cells to manage tasks more efficiently. Before v8.0, you could implement this kind of functionality using the addTaskLayer() method only. It serves for applying an additional layer with custom elements for tasks in the timeline.

This approach remains our recommended way of adding extra elements to the timeline. However, in some cases, it may be necessary to add content over specific cells of the Timeline, resulting in a large and complex custom Layer function.

To address this issue, we came up with an alternative approach for adding extra content in timeline cells.

Using DHTMLX Gantt 8.0, you can add your own content with images, icons, or other custom HTML elements to any timeline cells via a special template — timeline_cell_content.

Check the sample >

That is how the timeline_cell_content template is implemented in the code:

gantt.templates.timeline_cell_content = function (task, date) {
    if (17 <= task.id && task.id <= 20){
        const demoValue = randomValueForDate(date, 7)
        var value2 = Math.round(demoValue + demoValue * 0.15);
        return `<div class='cost'>${randomValueForDate(date, 7)}</div>
        <div class='cost'>${value2}</div>`;
    }
    return "";
};

When the timeline row is rendered, the template will be called for each visible cell and will receive a task object and the date of the cell as inputs. The method should return a string with any text or HTML elements as shown in the example above.

It should be noted that custom content in cells will be shown “below” the task bars, i.e. task bars will have a higher z-index. Therefore, the cell content won’t be visible when the taskbar is placed on top of it.

When it is necessary to show the content over the taskbar, you need to add a z-index to the custom element:

.cost{
  position:absolute;
  z-index: 5;
  pointer-events: none;
}

The new template approach is a more preferable option in terms of work effort and performance impact when it comes to adding content in timeline cells.

New Searching Option for Project Tasks

The DHTMLX Gantt component v8.0 comes with a new search option for the getTaskBy() method. To be more specific, now this method allows searching for project type tasks. In earlier versions, you had to resort to using a function as a parameter for the method to iterate not only regular tasks and milestones but also projects:

var task = gantt.getTaskBy(function(task){
   return task.text == "Project #2";
});
console.log(task);

It could cause some inconvenience and deter Gantt’s performance. Thus, we added an optional parameter aimed to specify which types of tasks should be returned.

For instance, you can select all types of tasks by setting their values in the third parameter to true:

gantt.getTaskBy("progress", 1, { task: true, project: true, milestone: true })

In case, you want to see just projects, you just need to set project: true in the parameter:

gantt.getTaskBy("progress", 1, { project: true})

These are the main features delivered in DHTMLX Gantt 8.0.

Source: release article published on March 20, 2023 on the DHTMLX blog.