I'm using DHTMLX Gantt Chart. As part of my project, I create a lot of custom layers to work with the chart but sadly, it's making my code very bloated having to declare each task to be rendered as a layer. My initial thought was to add the tasks using a loop and an object array. When I attempted this approach, it didn't work and nothing was rendered.
Here is my code so far:
//Gantt Initilisation
document.addEventListener("DOMContentLoaded", function (event) {
// Specifying the date format
gantt.config.xml_date = "%Y-%m-%d %H:%i";
gantt.config.readonly = true;
// Initializing gantt
gantt.init("positionsReport");
// Initiating data loading
gantt.load("/api/data/get");
// Initializing dataProcessor
var dp = new gantt.dataProcessor("/api/");
//Convert date to a usable format
gantt.attachEvent("onTaskLoading", function (task) {
task.options_start = gantt.date.parseDate(task.options_start, "xml_date");
task.options_end = gantt.date.parseDate(task.options_end, "xml_date");
task.f2_onhire = gantt.date.parseDate(task.f2_onhire, "xml_date");
task.f2_offhire = gantt.date.parseDate(task.f2_offhire, "xml_date");
task.f2_options_start = gantt.date.parseDate(task.f2_options_start, "xml_date");
task.f2_options_end = gantt.date.parseDate(task.f2_options_end, "xml_date");
task.f3_onhire = gantt.date.parseDate(task.f3_onhire, "xml_date");
task.f3_offhire = gantt.date.parseDate(task.f3_offhire, "xml_date");
return true;
});
This is the basic setup before any work with layers, I initialise the Gantt, convert some date times to a format it understands and then define my API and required data.
//Fixture Layers
gantt.addTaskLayer(function draw_planned(task) {
var fixtureArray = [
{
onhire: task.start_date,
offhire: task.end_date,
charterer: task.current_charterer
},
{
onhire: task.f2_onhire,
offhire: task.f2_offhire,
charterer: task.f2_charterer
},
{
onhire: task.f3_onhire,
offhire: task.f3_offhire,
charterer: task.f3_charterer
}
];
For the purposes of this question, I've created a short array based on the task data I've required which is limited to three items.
for (i = 0; i < fixtureArray.length; i++) {
var sizes = gantt.getTaskPosition(fixtureArray, fixtureArray.onhire, fixtureArray.offhire);
var el = document.createElement('div');
el.className = 'gantt_task_content';
return el;
}
return false;
});
I then attempt to create the required layers for each item in my array.
gantt.config.columns = [
{ name: "text", tree: false, width: 150, resize: true, align: "left", label: "Vessel" },
{ name: "start_date", align: "center", width: 150, resize: true, align: "left", label: "Onhire" },
{ name: "duration", align: "center", width: 70, resize: true, hide: true }
];
//Month format
gantt.config.scale_unit = "month";
gantt.config.date_scale = "%M";
//View
gantt.config.start_date = new Date(2019, 01, 01);
gantt.config.end_date = new Date(2020, 01, 01);
// and attaching it to gantt
dp.init(gantt);
// setting the REST mode for dataProcessor
dp.setTransactionMode("REST");
});
Then I finish off with a date range, scale and rest mode settings, and the final initilisation statement.
The Gantt chart works fine and there are no error messages, but, it only renders one item from my array loop, the rest never appear. Is my approach correct for this setup?
You can have only one return value from a function, your code exits addTaskLayer
function on the first iteration.
If you want it to display several elements, you can create an additional 'wrapper' element, append your items to it and return the wrapper
element from the function:
var wrapper = document.createElement('div'); //!!!
for (i = 0; i < fixtureArray.length; i++) {
var sizes = gantt.getTaskPosition(fixtureArray, fixtureArray.onhire, fixtureArray.offhire);
var el = document.createElement('div');
el.className = 'gantt_task_content';
wrapper.appendChild(el); //!!!
}
if(wrapper.children.length){
return wrapper; //!!!
}
return false;
For example, you can look at this demo: https://docs.dhtmlx.com/gantt/samples/04_customization/18_subtasks_displaying.html - check Task #2 row, there are multiple elements added by addTaskLayer function using the very same approach.