DEV Community

Cover image for Deep DHTMLX Gantt Customization: New Looks of Tasks, Month Marker, and Customized Grid
Pavel Lazarev
Pavel Lazarev

Posted on

Deep DHTMLX Gantt Customization: New Looks of Tasks, Month Marker, and Customized Grid

There are as many requirements as many projects. We often receive requests from developers about how far they can go in customizing DHTMLX Gantt. Not everyone knows that our JS Gantt chart allows changing virtually every aspect of its appearance. The resulting Gantt built with DHTMLX can look very different from the original one.

We start a new series of articles on the blog, where we will uncover the most exemplary cases of customizing DHTMLX Gantt to demonstrate its versatility.

Use Case: New Project Appearance, Current Month Marker, and Collapsible Grid

The default view of DHTMLX Gantt displays project and task names written inside bars. The project bar usually has a rectangle shape, just like the task bar, and differs from tasks in color. However, this is not the only way to show projects and tasks in DHTMLX Gantt. Our Gantt chart library is very flexible in terms of customization and allows visualizing data in almost any imaginable way. Don’t take our word for it, but look at a live example.

javascript-gantt-customization

Check the code snippet >

Here, you can see projects nicely depicted with thin, colorful lines and labels on top, project dates and duration marked next to their names. Thus, end-users can quickly grasp how much time each project will take.

Task labels are also located to the right of the task bar. The current month is clearly highlighted in the timescale not to get lost on the timeline. Besides, there is a toggle button for collapsing the grid section to make more room for the Gantt chart.

Such a customization contributes to the transparency of the workflow and can be especially useful for small and medium-sized projects. It also makes your Gantt more user-friendly and easier to manage, switching between the view with an expanded grid section and a full-screen chart.

Customization Guide

Let’s delve into what is under the hood of such a Gantt chart made by DHTMLX.

Current Month Marker

We start with the time scales and the vertical marker used in the Gantt timeline. The configuration of scales is specified via the scales property:

gantt.config.scales = [
    {
        unit: "quarter", step: 1, format: function (date) {
            const quarter = (date.getMonth() % 3) + 1;
            const year = date.getFullYear();
            return `<b>Q${quarter}</b> ${year}`;
        }
    },
    {
        unit: "month", step: 1, format: function (date) {
            const monthName = gantt.date.date_to_str("%F")(date)
            const nextDate = gantt.date.add(date, 1, "month");
            if (+date <= +today && +today <= +nextDate) {
                return `<div class="current_month">${monthName}</div>`;
            }
            else {
                return monthName;
            }
        }
    },
]
Enter fullscreen mode Exit fullscreen mode

In the array of the scales config, we specify two built-in types of scales, “quarter” and “month”. In the cells of both scale types, we can display any values or HTML elements, but they won’t change the width of cells. For instance, one of the cells in the lower scale with names of months includes a custom element with a specific class for coloring this cell with CSS styles. This element highlights the current month, which is specified in the today parameter:

const today = new Date(2023, 05, 18)
const todayMarker = gantt.addMarker({
    start_date: today,
    css: "today",
});
Enter fullscreen mode Exit fullscreen mode

The today parameter is also used in the addMarker() method for adding a vertical marker that highlights the current month. In the marker configuration, we specify the Date object that sets the marker’s date and the CSS class for adding the marker color. Since we do not apply the text parameter in the addMarker() method, the marker will be shown as a simple line.

Task Behavior

It is necessary to say a few words about the interaction with tasks in the Gantt timeline. End-users can move a given task along the timeline to any specific point and it won’t snap to the beginning or end of any cell. To make it happen, we changed the value of the round_dnd_dates parameter to false in the gantt.config object:

gantt.config.round_dnd_dates = false;
Enter fullscreen mode Exit fullscreen mode

Following the requirements of this demo project, we also added the ability to move project tasks and disabled the display of dependencies (links) between tasks and the progress of tasks:

gantt.config.drag_project = true;
gantt.config.drag_progress = false;
gantt.config.drag_links = false;
Enter fullscreen mode Exit fullscreen mode

Grid

Let’s move on to the grid section. In the grid part of the Gantt chart, there are two columns. The first column contains the names of tasks, while the second one provides their timeframes. Using the template function, you can add any text or HTML elements in the cells of the grid column:

gantt.config.columns = [
    { name: "text", label: " ", width: 300, tree: true },
    {
        name: "dates", label: getToggleButton(), align: "center", template: function (task) {
            if (task.type == "project") {
                return ""
            }


            return taskDatesFormat(task)
        }
    },
];
Enter fullscreen mode Exit fullscreen mode

Now we want to focus on the taskDatesFormat function that returns the needed string from a task object:

function taskDatesFormat(task) {
    let startMonth = gantt.date.date_to_str("%M");
    let endMonth = startMonth;
    let day = gantt.date.date_to_str("%j");


    if (task.start_date.getMonth() == task.end_date.getMonth()) {
        endMonth = gantt.date.date_to_str("");
    }
    const start_date = `${startMonth(task.start_date)} ${day(task.start_date)} - `;
    const end_date = `${endMonth(task.end_date)} ${day(task.end_date)}`;
    return start_date + end_date;

}
Enter fullscreen mode Exit fullscreen mode

This function works as follows:

  • It converts the task start date into a string, thereby showing only the month’s name.

  • If a task starts and ends in the same month, the month’s name will be seen only before the start date. If start and end dates belong to different months, the start month will show before the start date and the end month – before the end date.

  • Dates follow the name of the month.

There is a special toggle button that allows collapsing and expanding the grid section. To add this button, we specified the getToggleButton() function inside the label parameter. Depending on the current state of the grid, this function returns different values. When the button is clicked, we change the return value and the width in the grid_width config:

function toggleGrid() {
    if (gridToggleText == "lt") {
        gantt.config.grid_width = 80;
        gridToggleText = "gt"
    }
    else {
        gantt.config.grid_width = initialGridWidth;
        gridToggleText = "lt"
    }
    gantt.config.columns[1].label = getToggleButton();
    gantt.render();
}
Enter fullscreen mode Exit fullscreen mode

Alternatively, the grid size can be changed with a resizer. The min_grid_column_width parameter sets the minimum width for each column, so you cannot make the grid smaller than the specified size. Since our Gantt chart has two columns and the value of the min_grid_column_width parameter is 30px, the minimum grid width is 60px.

gantt.config.min_grid_column_width = 30;
Enter fullscreen mode Exit fullscreen mode

Colored circles in the grid area are specified in the grid_folder template:

gantt.templates.grid_folder = function (task) {
    return `<div style="color:${task.color}" class="project_icon">&nbsp;•&nbsp;</div>`;
};
Enter fullscreen mode Exit fullscreen mode

The returned custom element includes a special symbol "•". The color and size of circles are specified with CSS styles.

The grid_folder template is displayed for tasks with child elements, while an empty string ("") is returned in the grid_file template for other tasks:

gantt.templates.grid_file = function (item) {
    return "";
};
Enter fullscreen mode Exit fullscreen mode

The task_row_class template hides a border under tasks with child elements:

gantt.templates.task_row_class = function (start, end, task) {
    if (task.type == "project") {
        return "project_row";
    }
};
Enter fullscreen mode Exit fullscreen mode

Task Appearance

Finally, let’s shed some light on how to customize projects and tasks in the Gantt chart. Since there should be no text inside taskbars, the task_text template returns an empty string:

gantt.templates.task_text = function (start, end, task) {
    return "";
};
Enter fullscreen mode Exit fullscreen mode

Text labels are displayed on the right side with the help of the rightside_text template:

gantt.templates.rightside_text = function (start, end, task) {
    if (task.type != "project") {
        return task.text;
    }
};
Enter fullscreen mode Exit fullscreen mode

In our demo, the rightside_text template doesn’t return anything for project tasks. Instead, we use the addTaskLayer() method, which allows displaying any text or HTML element inside the Gantt timeline. For project tasks, we return a task name, its duration, and dates in the same format used in the Gantt grid with the help of the custom taskDatesFormat function. These values are separated from one another with a special dot symbol "•". The positioning of custom elements is calculated using the getTaskPosition() method:

gantt.addTaskLayer(function (task) {
    if (task.type == "project") {
        const sizes = gantt.getTaskPosition(task, task.start_date, task.end_date);
        const el = document.createElement('div');
        const dot = `<span class="dot">•</span>`
        el.innerHTML = task.text + dot + taskDatesFormat(task) + dot + task.duration + "days";
        el.style.left = sizes.left + 10 + 'px';
        el.style.top = sizes.top + 'px';
        el.style.zIndex = 1;
        el.style.marginTop = "7px";
        el.style.position = "absolute";
        el.style.lineHeight = "16px";
        return el;
    }
});
Enter fullscreen mode Exit fullscreen mode

That’s it! With this step-by-step guide, you can achieve the same result and create a custom Gantt chart like in our use case.

Conclusion

The rich API of the DHTMLX Gantt component allows you to customize the look and feel of almost any element to your liking. So, if your web project lacks a Gantt chart and you have a clear vision of how it should look, DHTMLX Gantt will help bring your idea to life much faster. You can estimate its capabilities by downloading a free 30-day trial version.

Also, feel free to send us your ideas for Gantt customizations – and our tech support team will do their best to help you achieve the desired result.

The article is originally published on the DHTMLX blog.

Top comments (0)