HelpBot Assistant

How can I help you?

Work Breakdown Structure (WBS) in Angular Gantt Chart Component

1 Feb 202617 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 Chart 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 as GanttComponent).enableAutoWbsUpdate = false;
            this.isRowDropped = false;
        }
    }

    public actionBegin(args: any): void {
        if (args.requestType === "beforeDrop") {
            this.isRowDropped = true;
            (this.ganttInstance as GanttComponent).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 Chart 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.