Work Breakdown Structure (WBS) in Angular Gantt component
15 Oct 202517 minutes to read
The Work Breakdown Structure (WBS) organizes project tasks hierarchically by assigning unique codes to each task. This improves task visibility and management, especially in large-scale construction or enterprise-level software projects.
Configuration and implementation
To enable WBS in the Gantt component:
- Enable WBS Codes: Set enableWBS to true to automatically generate unique task codes and define their predecessors.
- Auto-Update Codes: Set enableAutoWbsUpdate to true to maintain accurate WBS codes during operations such as sorting, editing, or drag-and-drop.
import { GanttAllModule } from '@syncfusion/ej2-angular-gantt';
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { WBSData } from './data';
@Component({
imports: [ GanttAllModule],
standalone: true,
selector: 'app-root',
template:
`<ejs-gantt id="ganttWbs" #gantt height="450px" [dataSource]="data" [taskFields]="taskSettings" [columns]="columns"
[timelineSettings]="timelineSettings" [labelSettings]="labelSettings" [editSettings]="editSettings"
[allowFiltering]="true" [allowSorting]="true" [toolbar]="toolbar" [treeColumnIndex]="2"
[filterSettings]="filterSettings" [allowSelection]="true" [projectStartDate]="projectStartDate"
[projectEndDate]="projectEndDate" [enableWBS]="true" [enableAutoWbsUpdate]="true"
[splitterSettings]="splitterSettings" [rowHeight]="rowHeight" [taskbarHeight]="taskbarHeight"
[allowUnscheduledTasks]="allowUnscheduledTasks" [eventMarkers]="eventMarkers">
</ejs-gantt>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent implements OnInit {
public data?: object[];
public taskSettings?: object;
public columns?: object[];
public toolbar?: string[];
public editSettings?: object;
public splitterSettings?: object;
public selectionSettings?: object;
public tooltipSettings?: object;
public filterSettings?: object;
public timelineSettings?: object;
public labelSettings?: object;
public height?: string;
public taskbarHeight?: number;
public rowHeight?: number;
public allowUnscheduledTasks?: boolean;
public enableWBS?: boolean;
public enableAutoWbsUpdate?: boolean;
public projectStartDate?: Date;
public projectEndDate?: Date;
public eventMarkers?: object[];
public ngOnInit(): void {
this.data = WBSData;
this.taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
parentID: 'ParentId'
};
this.columns = [
{ field: 'TaskID', headerText: 'Task ID', visible: false },
{ field: 'WBSCode', headerText: 'WBS Code', width: '150px' },
{ field: 'TaskName', headerText: 'Task Name', allowReordering: false, width: '260px' },
{ field: 'StartDate', headerText: 'Start Date', width: '140px' },
{ field: 'WBSPredecessor', headerText: 'WBS Predecessor', width: '190px' },
{ field: 'Duration', headerText: 'Duration', allowEditing: false, width: '130px' },
{ field: 'Progress', headerText: 'Progress' },
];
this.eventMarkers = [
{
day: new Date('04/2/2024'),
label: 'Project Initiation'
}
];
this.editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
};
this.toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll'];
this.splitterSettings = { columnIndex: 4 };
this.selectionSettings = { mode: 'Row', type: 'Single', enableToggle: false };
this.tooltipSettings = { showTooltip: true };
this.filterSettings = { type: 'Menu' };
this.timelineSettings = {
showTooltip: true,
topTier: { unit: 'Week', format: 'dd/MM/yyyy' },
bottomTier: { unit: 'Day', count: 1 }
};
this.labelSettings = {
taskLabel: '${Progress}%'
};
this.taskbarHeight = 20;
this.rowHeight = 40;
this.height = '550px';
this.allowUnscheduledTasks = true;
this.enableWBS = true;
this.enableAutoWbsUpdate = true;
this.projectStartDate = new Date('03/31/2024');
this.projectEndDate = new Date('05/30/2024');
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Managing WBS code updates
To optimize performance, WBS code updates can be controlled using the actionBegin and dataBound events. This is especially useful during operations like row drag-and-drop, where auto-update is triggered only during that specific action to ensure efficient and accurate code handling.
In the following example, WBS auto-update is enabled only during the row drag and drop action using these events.
import { GanttAllModule } from '@syncfusion/ej2-angular-gantt';
import { Component, ViewEncapsulation, ViewChild, OnInit } from '@angular/core';
import { GanttComponent } from '@syncfusion/ej2-angular-gantt';
import { WBSData } from './data';
@Component({
imports: [GanttAllModule],
standalone: true,
selector: 'app-root',
template:
`<ejs-gantt id="ganttWbs" #gantt height="450px" [dataSource]="data" [taskFields]="taskSettings" [columns]="columns"
[timelineSettings]="timelineSettings" [labelSettings]="labelSettings" [editSettings]="editSettings"
[allowFiltering]="true" [allowSorting]="true" [toolbar]="toolbar" [treeColumnIndex]="2"
[filterSettings]="filterSettings" [allowSelection]="true" [projectStartDate]="projectStartDate"
[projectEndDate]="projectEndDate" [enableWBS]="true" [enableAutoWbsUpdate]="false"
[splitterSettings]="splitterSettings" [rowHeight]="rowHeight" [taskbarHeight]="taskbarHeight"
[allowUnscheduledTasks]="allowUnscheduledTasks" [eventMarkers]="eventMarkers" [allowRowDragAndDrop]="true" (dataBound)="dataBound()" (actionBegin)="actionBegin($event)">
</ejs-gantt>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent implements OnInit {
@ViewChild('gantt') public ganttInstance?: GanttComponent;
public isRowDropped: boolean = false;
public data?: object[];
public taskSettings?: object;
public columns?: object[];
public toolbar?: string[];
public editSettings?: object;
public splitterSettings?: object;
public selectionSettings?: object;
public tooltipSettings?: object;
public filterSettings?: object;
public timelineSettings?: object;
public labelSettings?: object;
public height?: string;
public taskbarHeight?: number;
public rowHeight?: number;
public allowUnscheduledTasks?: boolean;
public enableWBS?: boolean;
public enableAutoWbsUpdate?: boolean;
public projectStartDate?: Date;
public projectEndDate?: Date;
public eventMarkers?: object[];
public ngOnInit(): void {
this.data = WBSData;
this.taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
parentID: 'ParentId'
};
this.columns = [
{ field: 'TaskID', headerText: 'Task ID', visible: false },
{ field: 'WBSCode', headerText: 'WBS Code', width: '150px' },
{ field: 'TaskName', headerText: 'Task Name', allowReordering: false, width: '260px' },
{ field: 'StartDate', headerText: 'Start Date', width: '140px' },
{ field: 'WBSPredecessor', headerText: 'WBS Predecessor', width: '190px' },
{ field: 'Duration', headerText: 'Duration', allowEditing: false, width: '130px' },
{ field: 'Progress', headerText: 'Progress' },
];
this.eventMarkers = [
{
day: new Date('04/2/2024'),
label: 'Project Initiation'
}
];
this.editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true
};
this.toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll'];
this.splitterSettings = { columnIndex: 4 };
this.selectionSettings = { mode: 'Row', type: 'Single', enableToggle: false };
this.tooltipSettings = { showTooltip: true };
this.filterSettings = { type: 'Menu' };
this.timelineSettings = {
showTooltip: true,
topTier: { unit: 'Week', format: 'dd/MM/yyyy' },
bottomTier: { unit: 'Day', count: 1 }
};
this.labelSettings = {
taskLabel: '${Progress}%'
};
this.taskbarHeight = 20;
this.rowHeight = 40;
this.height = '550px';
this.allowUnscheduledTasks = true;
this.enableWBS = true;
this.enableAutoWbsUpdate = true;
this.projectStartDate = new Date('03/31/2024');
this.projectEndDate = new Date('05/30/2024');
}
public dataBound(): void {
if (this.isRowDropped) {
this.ganttInstance.enableAutoWbsUpdate = false;
this.isRowDropped = false;
}
}
public actionBegin(args: any): void {
if (args.requestType === "beforeDrop") {
this.isRowDropped = true;
this.ganttInstance.enableAutoWbsUpdate = true;
}
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Limitations
The WBS feature has a few limitations in the Gantt component:
- Editing of the WBS code and WBS predecessor columns is not supported.
- Load on demand is not supported with the WBS feature.
- WBS Code and WBS Predecessor fields cannot be mapped directly from the data source.