Search code examples
javascriptdhtmlx

How do I return my DHTMLX Gantt data using a loop?


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?


Solution

  • 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.