Critical path in Angular Gantt component
18 Oct 202524 minutes to read
The critical path represents the longest sequence of dependent tasks that determines the minimum project duration. Tasks on the critical path have zero or negative slack (float), meaning any delay in these tasks directly impacts the overall project completion date. The Angular Gantt component automatically calculates and highlights critical tasks in red with emphasized dependency connector lines when the enableCriticalPath property is enabled. Critical path analysis helps identify which tasks require immediate attention and cannot be delayed without affecting project deadlines.
Understanding critical path calculation
The component uses Critical Path Method (CPM) principles to identify critical tasks through a comprehensive calculation process that analyzes task dependencies, timing relationships, and slack values to determine which tasks have no scheduling flexibility. A task becomes critical when it has zero or negative slack, meaning any delay (even by a minute) shifts the entire project end date. This occurs because critical tasks are linked through dependencies, creating a chain reaction where delays propagate across the dependency network, ultimately affecting the project completion date.
Project end date determination: The calculation begins by determining the overall project end date. If the projectEndDate property is provided, it uses that value as the project completion reference. If projectEndDate is not specified, the component automatically calculates the project end date by examining all task end dates in the data source to find the latest completion point. This reference point determines how much delay each task can tolerate without affecting project completion.
Slack value calculation: For each task, the component calculates slack by measuring the time difference between the task’s end date and the project end date. Slack represents how much time a task can be delayed without affecting the project completion:
- Zero slack: The task must finish exactly on time. Any delay will push back the project end date, making it critical
- Negative slack: The task is already behind schedule or creates scheduling conflicts. This occurs when a task’s end date is beyond the project end date, or when dependency relationships create impossible timing constraints.
Parent-Child task relationships: In projects with hierarchical tasks, the critical path calculation focuses on dependencies rather than the parent-child structure used for task organization. For example, if Task 1.1 (a child task) depends on Task 2 (a parent task), only the tasks directly linked by the dependency are evaluated for criticality based on their timing. A parent task like Task 2 being critical does not automatically make its child tasks (e.g., Task 2.1, Task 2.2) critical, nor does a critical child task imply a critical parent. The component evaluates each task’s slack independently, ensuring that only tasks with zero or negative slack, driven by their dependency constraints, are marked as critical. This distinction allows precise identification of critical tasks without conflating organizational hierarchy with scheduling dependencies.
Dependency-based analysis: The component analyzes different dependency relationship types to determine slack impacts:
- Finish-to-Start: When a predecessor task ends after its successor should start, negative slack results from the timing conflict
- Start-to-Start: When a predecessor starts after its successor should start, the component calculates negative slack based on scheduling impossibility
- Finish-to-Finish and Start-to-Finish: These relationships can also produce negative slack when timing conflicts exist between connected tasks
- Offset and scheduling mode handling: When dependencies include time offsets (e.g., “+2 days” or “-1 hour”), the component adjusts slack calculations by factoring in the offset duration. The calculation differs for automatically scheduled versus manually scheduled tasks: automatic tasks use forward and backward pass algorithms to compute slack, while manual tasks compare their end dates directly against the project completion date.
Progress consideration: The component considers task completion progress. Only tasks with less than 100% progress can be marked as critical, since completed tasks cannot cause future delays. Tasks that end on or beyond the project end date automatically become critical regardless of their dependency relationships, as they directly determine the project completion timing.
Critical path setup and configuration
Critical path functionality requires the CriticalPathService to be injected in the providers array. The data source must contain tasks with valid start dates, end dates, and task dependencies properly mapped through the dependency field in taskFields.
Enable critical path display by setting enableCriticalPath to true, or add the CriticalPath option to the toolbar array to allow interactive toggling. The getCriticalTasks() method retrieves all tasks identified as critical at runtime.
The critical path recalculates automatically when task properties change, including start and end dates, duration modifications, dependency updates, or progress adjustments. This ensures the visualization remains accurate throughout project management workflows.
The following example demonstrates enabling critical path analysis:
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { GanttModule, CriticalPathService, ToolbarService, EditService } from '@syncfusion/ej2-angular-gantt'
import { ToolbarItem, EditSettingsModel } from '@syncfusion/ej2-angular-gantt';
import { projectNewData } from './data';
@Component({
imports: [GanttModule],
providers: [CriticalPathService, ToolbarService, EditService],
standalone: true,
selector: 'app-root',
template:
`<ejs-gantt id="ganttDefault" height="430px" [dataSource]="data" [enableCriticalPath]='true' [taskFields]="taskSettings" [editSettings] = "editSettings"></ejs-gantt>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent implements OnInit {
public data?: object[];
public taskSettings?: object;
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItem[];
public ngOnInit(): void {
this.data = projectNewData;
this.taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
child: 'subtasks'
},
this.editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
},
this.toolbar = ['CriticalPath']
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));export let projectNewData: Object[] = [
{
TaskID: 1,
TaskName: 'Product Concept',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 2, TaskName: 'Defining the product and its usage', StartDate: new Date('04/02/2019'), Duration: 3, Progress: 30 },
{ TaskID: 3, TaskName: 'Defining target audience', StartDate: new Date('04/02/2019'), Duration: 3 },
{
TaskID: 4, TaskName: 'Prepare product sketch and notes', StartDate: new Date('04/02/2019'), Duration: 2,
Predecessor: '2', Progress: 30
},
]
},
{
TaskID: 5, TaskName: 'Concept Approval', StartDate: new Date('04/02/2019'), Duration: 0, Predecessor: '3,4',
Indicators: [
{
'date': '04/10/2019',
'name': '#briefing',
'title': 'Product concept breifing',
}
]
},
{
TaskID: 6,
TaskName: 'Market Research',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 7,
TaskName: 'Demand Analysis',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 8, TaskName: 'Customer strength', StartDate: new Date('04/04/2019'), Duration: 4,
Predecessor: '5', Progress: 30
},
{ TaskID: 9, TaskName: 'Market opportunity analysis', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '5' }
]
},
{
TaskID: 10, TaskName: 'Competitor Analysis', StartDate: new Date('04/04/2019'), Duration: 4,
Predecessor: '7, 8', Progress: 30
},
{ TaskID: 11, TaskName: 'Product strength analsysis', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '9' },
{
TaskID: 12, TaskName: 'Research complete', StartDate: new Date('04/04/2019'), Duration: 0, Predecessor: '10',
Indicators: [
{
'date': '04/20/2019',
'name': '#meeting',
'title': '1st board of directors meeting',
}
]
}
]
},
{
TaskID: 13,
TaskName: 'Product Design and Development',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 14, TaskName: 'Functionality design', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 30, Predecessor: '12'
},
{ TaskID: 15, TaskName: 'Quality design', StartDate: new Date('04/04/2019'), Duration: 3, Predecessor: '12' },
{ TaskID: 16, TaskName: 'Define Reliability', StartDate: new Date('04/04/2019'), Duration: 2, Progress: 30, Predecessor: '15' },
{ TaskID: 17, TaskName: 'Identifying raw materials', StartDate: new Date('04/04/2019'), Duration: 2, Predecessor: '15' },
{
TaskID: 18,
TaskName: 'Define cost plan',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 19, TaskName: 'Manufacturing cost', StartDate: new Date('04/04/2019'),
Duration: 2, Progress: 30, Predecessor: '17'
},
{ TaskID: 20, TaskName: 'Selling cost', StartDate: new Date('04/04/2019'), Duration: 2, Predecessor: '17' }
]
},
{
TaskID: 21,
TaskName: 'Development of the final design',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 22, TaskName: 'Defining dimensions and package volume', StartDate: new Date('04/04/2019'),
Duration: 2, Progress: 30, Predecessor: '19,20'
},
{
TaskID: 23, TaskName: 'Develop design to meet industry standards', StartDate: new Date('04/04/2019'),
Duration: 2, Predecessor: '22'
},
{ TaskID: 24, TaskName: 'Include all the details', StartDate: new Date('04/04/2019'), Duration: 3, Predecessor: '23' }
]
},
{
TaskID: 25, TaskName: 'CAD Computer-aided design', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 30, Predecessor: '24'
},
{ TaskID: 26, TaskName: 'CAM Computer-aided manufacturing', StartDate: new Date('04/04/2019'), Duration: 3, Predecessor: '25' },
{
TaskID: 27, TaskName: 'Design complete', StartDate: new Date('04/04/2019'), Duration: 0, Predecessor: '26',
Indicators: [
{
'date': '05/18/2019',
'name': '#meeting',
'title': '2nd board of directors meeting',
}
]
}
]
},
{ TaskID: 28, TaskName: 'Prototype Testing', StartDate: new Date('04/04/2019'), Duration: 4, Progress: 30, Predecessor: '27' },
{ TaskID: 29, TaskName: 'Include feedback', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '28ss' },
{ TaskID: 30, TaskName: 'Manufacturing', StartDate: new Date('04/04/2019'), Duration: 5, Progress: 30, Predecessor: '28,29' },
{ TaskID: 31, TaskName: 'Assembling materials to finsihed goods', StartDate: new Date('04/04/2019'), Duration: 5, Predecessor: '30' },
{
TaskID: 32,
TaskName: 'Feedback and Testing',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 33, TaskName: 'Internal testing and feedback', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 45, Predecessor: '31'
},
{
TaskID: 34, TaskName: 'Customer testing and feedback', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 50, Predecessor: '33'
}
]
},
{
TaskID: 35,
TaskName: 'Final Product Development',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 36, TaskName: 'Important improvements', StartDate: new Date('04/04/2019'),
Duration: 4, Progress: 30, Predecessor: '34'
},
{
TaskID: 37, TaskName: 'Address any unforeseen issues', StartDate: new Date('04/04/2019'),
Duration: 4, Progress: 30, Predecessor: '36ss'
}
]
},
{
TaskID: 38,
TaskName: 'Final Product',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 39, TaskName: 'Branding product', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '37' },
{
TaskID: 40, TaskName: 'Marketing and presales', StartDate: new Date('04/04/2019'),
Duration: 4, Progress: 30, Predecessor: '39'
}
]
}
];The code enables critical path analysis by setting enableCriticalPath to true and injecting the CriticalPathService. The component automatically calculates slack values for all tasks and highlights those with zero or negative slack as critical tasks, displaying them with red taskbars and emphasized dependency lines.
Customizing critical path appearance
The queryTaskbarInfo event provides access to the isCritical property for each task, enabling custom styling beyond the default red highlighting. Modify the taskbarBgColor, progressBarBgColor, or other visual properties to create distinct visual indicators for critical tasks.
The following example demonstrates custom styling for critical tasks using the queryTaskbarInfo event:
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { GanttModule, CriticalPathService, IQueryTaskbarInfoEventArgs, ToolbarService, EditService } from '@syncfusion/ej2-angular-gantt'
import { ToolbarItem, EditSettingsModel } from '@syncfusion/ej2-angular-gantt';
import { projectNewData } from './data';
@Component({
imports: [GanttModule],
providers: [CriticalPathService, ToolbarService, EditService],
standalone: true,
selector: 'app-root',
template:
`<ejs-gantt id="ganttDefault" height="430px" [dataSource]="data" [enableCriticalPath]='true' [taskFields]="taskSettings" (queryTaskbarInfo)="queryTaskbarInfo($event)" [editSettings] = "editSettings"></ejs-gantt>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
public data?: object[];
public taskSettings?: object;
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItem[];
public ngOnInit(): void {
this.data = projectNewData;
this.taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
child: 'subtasks'
},
this.editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
},
this.toolbar = ['CriticalPath']
}
public queryTaskbarInfo(args: IQueryTaskbarInfoEventArgs) {
if ((args.data.isCritical || args.data.slack === '0 day') && !args.data.hasChildRecords) {
args.taskbarBgColor = 'rgb(242, 210, 189)';
args.progressBarBgColor = 'rgb(201, 169, 166)';
}
};
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));export let projectNewData: Object[] = [
{
TaskID: 1,
TaskName: 'Product Concept',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 2, TaskName: 'Defining the product and its usage', StartDate: new Date('04/02/2019'), Duration: 3, Progress: 30 },
{ TaskID: 3, TaskName: 'Defining target audience', StartDate: new Date('04/02/2019'), Duration: 3 },
{
TaskID: 4, TaskName: 'Prepare product sketch and notes', StartDate: new Date('04/02/2019'), Duration: 2,
Predecessor: '2', Progress: 30
},
]
},
{
TaskID: 5, TaskName: 'Concept Approval', StartDate: new Date('04/02/2019'), Duration: 0, Predecessor: '3,4',
Indicators: [
{
'date': '04/10/2019',
'name': '#briefing',
'title': 'Product concept breifing',
}
]
},
{
TaskID: 6,
TaskName: 'Market Research',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 7,
TaskName: 'Demand Analysis',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 8, TaskName: 'Customer strength', StartDate: new Date('04/04/2019'), Duration: 4,
Predecessor: '5', Progress: 30
},
{ TaskID: 9, TaskName: 'Market opportunity analysis', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '5' }
]
},
{
TaskID: 10, TaskName: 'Competitor Analysis', StartDate: new Date('04/04/2019'), Duration: 4,
Predecessor: '7, 8', Progress: 30
},
{ TaskID: 11, TaskName: 'Product strength analsysis', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '9' },
{
TaskID: 12, TaskName: 'Research complete', StartDate: new Date('04/04/2019'), Duration: 0, Predecessor: '10',
Indicators: [
{
'date': '04/20/2019',
'name': '#meeting',
'title': '1st board of directors meeting',
}
]
}
]
},
{
TaskID: 13,
TaskName: 'Product Design and Development',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 14, TaskName: 'Functionality design', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 30, Predecessor: '12'
},
{ TaskID: 15, TaskName: 'Quality design', StartDate: new Date('04/04/2019'), Duration: 3, Predecessor: '12' },
{ TaskID: 16, TaskName: 'Define Reliability', StartDate: new Date('04/04/2019'), Duration: 2, Progress: 30, Predecessor: '15' },
{ TaskID: 17, TaskName: 'Identifying raw materials', StartDate: new Date('04/04/2019'), Duration: 2, Predecessor: '15' },
{
TaskID: 18,
TaskName: 'Define cost plan',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 19, TaskName: 'Manufacturing cost', StartDate: new Date('04/04/2019'),
Duration: 2, Progress: 30, Predecessor: '17'
},
{ TaskID: 20, TaskName: 'Selling cost', StartDate: new Date('04/04/2019'), Duration: 2, Predecessor: '17' }
]
},
{
TaskID: 21,
TaskName: 'Development of the final design',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 22, TaskName: 'Defining dimensions and package volume', StartDate: new Date('04/04/2019'),
Duration: 2, Progress: 30, Predecessor: '19,20'
},
{
TaskID: 23, TaskName: 'Develop design to meet industry standards', StartDate: new Date('04/04/2019'),
Duration: 2, Predecessor: '22'
},
{ TaskID: 24, TaskName: 'Include all the details', StartDate: new Date('04/04/2019'), Duration: 3, Predecessor: '23' }
]
},
{
TaskID: 25, TaskName: 'CAD Computer-aided design', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 30, Predecessor: '24'
},
{ TaskID: 26, TaskName: 'CAM Computer-aided manufacturing', StartDate: new Date('04/04/2019'), Duration: 3, Predecessor: '25' },
{
TaskID: 27, TaskName: 'Design complete', StartDate: new Date('04/04/2019'), Duration: 0, Predecessor: '26',
Indicators: [
{
'date': '05/18/2019',
'name': '#meeting',
'title': '2nd board of directors meeting',
}
]
}
]
},
{ TaskID: 28, TaskName: 'Prototype Testing', StartDate: new Date('04/04/2019'), Duration: 4, Progress: 30, Predecessor: '27' },
{ TaskID: 29, TaskName: 'Include feedback', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '28ss' },
{ TaskID: 30, TaskName: 'Manufacturing', StartDate: new Date('04/04/2019'), Duration: 5, Progress: 30, Predecessor: '28,29' },
{ TaskID: 31, TaskName: 'Assembling materials to finsihed goods', StartDate: new Date('04/04/2019'), Duration: 5, Predecessor: '30' },
{
TaskID: 32,
TaskName: 'Feedback and Testing',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 33, TaskName: 'Internal testing and feedback', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 45, Predecessor: '31'
},
{
TaskID: 34, TaskName: 'Customer testing and feedback', StartDate: new Date('04/04/2019'),
Duration: 3, Progress: 50, Predecessor: '33'
}
]
},
{
TaskID: 35,
TaskName: 'Final Product Development',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{
TaskID: 36, TaskName: 'Important improvements', StartDate: new Date('04/04/2019'),
Duration: 4, Progress: 30, Predecessor: '34'
},
{
TaskID: 37, TaskName: 'Address any unforeseen issues', StartDate: new Date('04/04/2019'),
Duration: 4, Progress: 30, Predecessor: '36ss'
}
]
},
{
TaskID: 38,
TaskName: 'Final Product',
StartDate: new Date('04/04/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 39, TaskName: 'Branding product', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: '37' },
{
TaskID: 40, TaskName: 'Marketing and presales', StartDate: new Date('04/04/2019'),
Duration: 4, Progress: 30, Predecessor: '39'
}
]
}
];The event handler checks the isCritical flag and applies custom colors to taskbars, allowing project-specific visual distinctions for critical path tasks while maintaining clear identification of project bottlenecks.