Skip to main content
Back to examples
Professional demos/Gantt + Scheduler synchronization
Loading live demo…from dhtmlxcode.com
Professional demos

Gantt + Scheduler synchronization

Synchronize tasks and events between DHTMLX Gantt and Scheduler components in a shared view.

/* Scheduler part */
scheduler.plugins({
  readonly: true,
  units: true,
});

scheduler.config.date_format = "%d-%m-%Y-%H:%i";
scheduler.config.readonly_form = true;
scheduler.config.details_on_dblclick  = true;
scheduler.config.cascade_event_display = true;

scheduler.locale.labels.unit_tab = "Unit"

scheduler.createUnitsView({
    name:"unit",
    property:"section_id", //the mapped data property
    list:[              //defines the units of the view
        {key:1, label:"Section A"},
        {key:2, label:"Section B"},
        {key:3, label:"Section C"}  
    ],
    days:3
});

function block_readonly(id){ 
  if (!id) return true;
  return !this.getEvent(id).comes_from_gantt;
}
scheduler.attachEvent("onBeforeDrag",block_readonly)
scheduler.attachEvent("onClick",block_readonly)

scheduler.attachEvent("onViewChange", function(new_mode , new_date){
  gantt.config.start_date = new Date(scheduler.getState().min_date);
  gantt.config.end_date = new Date(scheduler.getState().max_date);
  if(gantt.$container){
    gantt.render();
  }
}); 

scheduler.templates.event_text=function(start, end, event){
    return `${event.text} ${Math.floor(event.progress*100)}%`;
}

scheduler.init('scheduler_here',new Date(2025,3,1),"unit"); 


/* Gantt part */
gantt.config.show_tasks_outside_timescale = true;
gantt.config.duration_unit = "hour";
gantt.config.duration_step = 1; 
gantt.config.round_dnd_dates = false;
gantt.init("gantt_here");

gantt.config.lightbox.sections = [
    {name:"description", height:38, map_to:"text", type:"textarea",focus:true},
    {name:"section", height:22, map_to:"section_id", type:"select", 
        options: [{key:1, label: "Section A"},{key:2, label: "Section B"},{key:3, label: "Section C"}]}, 
    {name:"time", time_format:["%d","%m","%Y","%H:%i"], height:72, type:"duration", map_to:"auto"}];

gantt.attachEvent("onTaskLoading", function(task){ 
  if(task.type != "project"){
    task.comes_from_gantt = true;
    scheduler.addEvent(task)
  }
  return true;
});

gantt.attachEvent("onAfterTaskUpdate", function(id,item){
  scheduler.updateEvent(item)
  scheduler.updateView();
});
gantt.attachEvent("onAfterTaskAdd", function(id,item){ 
    item.comes_from_gantt = true;
    scheduler.addEvent(item)
});
gantt.attachEvent("onAfterTaskDelete", function(id,item){
  scheduler.deleteEvent(id)
  scheduler.updateView();
}); 

gantt.attachEvent("onTaskSelected", function(id){
    const task = gantt.getTask(id);
    gantt.config.start_date = new Date(task.start_date);
    gantt.config.end_date = gantt.date.add(task.start_date, 7, "day");
    scheduler.setCurrentView(new Date(task.start_date))

})

const tasks = {
    "data": [
        { "id": "10", "section_id": 1,  "text": "Project #1", "start_date": "31-03-2025 02:00", "duration": 22, "order": 10, "progress": 0.4, "open": true },
        { "id": "1",   "section_id": 2, "text": "Task #1", "start_date": "02-04-2025 03:00", "duration": 12, "order": 10, "progress": 0.6, "parent": "10" },
        { "id": "2", "section_id": 3, "text": "Task #2", "start_date": "01-04-2025 04:00", "duration": 15, "order": 20, "progress": 0.6, "parent": "10" },
        { "id": "20",  "section_id": 1, "text": "Project #2", "start_date": "01-04-2025 06:00", "duration": 16, "order": 10, "progress": 0.4, "type": "project", "open": true },
        { "id": "3", "section_id": 3,  "text": "Task #3", "start_date": "02-04-2025 06:00", "duration": 27, "order": 10, "progress": 0.6, "parent": "20" },
        { "id": "4", "section_id": 2, "text": "Task #4", "start_date": "05-04-2025 08:00", "duration": 5, "order": 20, "progress": 0.6, "parent": "20" }
    ],
    "links": [
        { "id": 1, "source": 1, "target": 2, "type": "0" },
        { "id": 2, "source": 2, "target": 3, "type": "0" },
        { "id": 3, "source": 3, "target": 4, "type": "0" },
        { "id": 4, "source": 2, "target": 5, "type": "0" }
    ]
}
gantt.parse(tasks);

scheduler.message("Change task in gantt chart and scheduler will reflect changes")
<div id="scheduler_here" class="dhx_cal_container" style="width:100%; height:50vh;">
</div>
<div id="gantt_here" style="width:100%; height:45vh;"></div>