Resources in Angular Gantt component

18 Oct 202524 minutes to read

Resources in the Angular Gantt component represent people, equipment, or materials allocated to tasks, visualized in taskbars and labels for clear utilization tracking. Assigned via the resources property, resources map to tasks using resourceFields for ID, name, unit, and group. This enables display of resource names in columns or labels with labelSettings, highlighting workloads and overallocation. The queryTaskbarInfo event customizes taskbar styles based on resources, such as color-coding. Resources include ARIA labels for accessibility, ensuring screen reader compatibility, and adapt to responsive designs, though narrow screens may truncate names for multiple assignments. By default, resources allocate 100% unit if unspecified.

Configure resource collection

The resource collection defines available resources as JSON objects with ID, name, unit, and group, mapped via resourceFields:

  • id: Maps to a unique identifier for task assignment.
  • name: Maps to the resource name displayed in labels or columns.
  • unit: Maps to the work capacity percentage (0-100%) per day.
  • group: Maps to categories for grouping resources.

The following code demonstrates resource collection setup:

var projectResources = [
    { resourceId: 1, resourceName: 'Martin Tamer', resourceGroup: 'Planning Team', resourceUnit: 50},
    { resourceId: 2, resourceName: 'Rose Fuller', resourceGroup: 'Testing Team', resourceUnit: 70 },
    { resourceId: 3, resourceName: 'Margaret Buchanan', resourceGroup: 'Approval Team' },
    { resourceId: 4, resourceName: 'Fuller King', resourceGroup: 'Development Team' },
    { resourceId: 5, resourceName: 'Davolio Fuller', resourceGroup: 'Approval Team' },
    { resourceId: 6, resourceName: 'Van Jack', resourceGroup: 'Development Team', resourceUnit: 40 },
];

public resourceFields = {
    id: 'resourceId',
    name: 'resourceName',
    unit: 'resourceUnit',
    group: 'resourceGroup'
};

This configuration maps resources for assignment and display.

Assign resources to tasks

Resources are assigned to tasks using resource IDs in the data source, mapped via taskFields.resourceInfo. Assignments can be added or edited dynamically via cell or dialog editing, triggered by double-clicking.

Single resource assignment:
Assign a single resource without unit for default 100% allocation.

{ 
    TaskID: 2, 
    TaskName: 'Identify site location', 
    StartDate: new Date('04/02/2019'), 
    Duration: 0, 
    Progress: 50, 
    resources: [1] 
}

Multiple resources with custom units:
Assign multiple resources with specific units.

{
    TaskID: 2, 
    TaskName: 'Identify site location', 
    StartDate: new Date('03/29/2019'), 
    Duration: 2,
    Progress: 30,  
    resources: [{ resourceId: 1, unit: 70 }, 6]
}

Units from the resource collection apply unless overridden at the task level.

The following example shows resource assignment:

import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { GanttModule } from '@syncfusion/ej2-angular-gantt'
import { projectNewData } from './data';

@Component({
    imports: [GanttModule],
    standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt height="430px" [dataSource]="data" [taskFields]="taskSettings" [treeColumnIndex]="1" [projectStartDate]="projectStartDate" [projectEndDate]="projectEndDate" [labelSettings]="labelSettings" [resourceFields]="resourceFields" [columns]="columns" [resources]="resources"></ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})

export class AppComponent implements OnInit {
    public data?: object[];
    public resources?: object[];
    public taskSettings?: object;
    public labelSettings?: object;
    public projectStartDate?: Date;
    public projectEndDate?: Date;
    public resourceFields?: object;
    public columns?: object[];

    public ngOnInit(): void {
        this.data = projectNewData
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            endDate: 'EndDate',
            duration: 'Duration',
            progress: 'Progress',
            dependency: 'Predecessor',
            resourceInfo: 'resources',
            child: 'subtasks'
        };
        this.labelSettings = {
            leftLabel: 'TaskName',
            rightLabel: 'resources'
        };
        this.resourceFields = {
            id: 'resourceId',
            name: 'resourceName',
            unit: 'Unit'
        };
        this.columns = [
            { field: 'TaskID', visible: false },
            { field: 'TaskName', headerText: 'Task Name', width: '180' },
            { field: 'resources', headerText: 'Resources', width: '160' },
            { field: 'Duration', width: '100' }
        ];
        this.projectStartDate = new Date('03/25/2019');
        this.projectEndDate = new Date('07/28/2019');
        this.resources = [
            { resourceId: 1, resourceName: 'Martin Tamer' },
            { resourceId: 2, resourceName: 'Rose Fuller' },
            { resourceId: 3, resourceName: 'Margaret Buchanan' },
            { resourceId: 4, resourceName: 'Fuller King' },
            { resourceId: 5, resourceName: 'Davolio Fuller' },
            { resourceId: 6, resourceName: 'Van Jack' },
            { resourceId: 7, resourceName: 'Fuller Buchanan' },
            { resourceId: 8, resourceName: 'Jack Davolio' },
            { resourceId: 9, resourceName: 'Tamer Vinet' },
            { resourceId: 10, resourceName: 'Vinet Fuller' },
            { resourceId: 11, resourceName: 'Bergs Anton' },
            { resourceId: 12, resourceName: 'Construction Supervisor' }
        ];
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
/**
 * TreeGrid DataSource
 */

export let projectNewData: Object[] = [
    {
        TaskID: 1,
        TaskName: 'Project initiation',
        StartDate: new Date('03/29/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            {
                TaskID: 2, TaskName: 'Identify site location', StartDate: new Date('03/29/2019'), Duration: 2,
                Progress: 30, resources: [{ resourceId: 1, Unit: 70 }, 6]
            },
            {
                TaskID: 3, TaskName: 'Perform soil test', StartDate: new Date('03/29/2019'), Duration: 4,
                resources: [2, 3, 5]
            },
            {
                TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('03/29/2019'), Duration: 1,
                resources: [8, { resourceId: 9, Unit: 50 }], Progress: 30
            },
        ]
    },
    {
        TaskID: 5,
        TaskName: 'Project estimation', StartDate: new Date('03/29/2019'), EndDate: new Date('04/21/2019'),
        subtasks: [
            {
                TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('03/29/2019'),
                Duration: 3, Progress: 30, resources: [{ resourceId: 4, Unit: 50 }]
            },
            {
                TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/01/2019'), Duration: 3,
                resources: [4, 8]
            },
            {
                TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/01/2019'),
                Duration: 2, resources: [12, { resourceId: 5, Unit: 70 }]
            }
        ]
    },
    {
        TaskID: 9, TaskName: 'Sign contract', StartDate: new Date('04/01/2019'), Duration: 1,
        Progress: 30, resources: [12]
    }
];

Manage resource assignments

Add or remove resources via cell or dialog editing. Cell editing modifies assignments by double-clicking the resource cell, while dialog editing uses the resource tab in the edit dialog.

Resource cell editing
Alt text: Resource cell editing in the Gantt grid for assignment modifications.

Resource dialog editing
Alt text: Resource dialog editing tab for multiple allocations and units.

Customize resource styling

Customize resource display using column templates for the resource column and the queryTaskbarInfo event for taskbar styling based on assigned resources.

The following example demonstrates custom resource styling:

import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { NgIf } from '@angular/common';
import { GanttModule, IGanttData, IQueryTaskbarInfoEventArgs, } from '@syncfusion/ej2-angular-gantt';
import { editingResources, GanttData } from './data';

@Component({
    imports: [GanttModule, NgIf],
    standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt height="430px" [dataSource]="data"  [taskFields]="taskSettings" [allowResizing] = 'true' rowHeight='50' [splitterSettings]="splitterSettings" [resourceFields]="resourceFields" [resources]="resources"
        (queryTaskbarInfo) = "queryTaskbarInfo($event)">
            <e-columns>
                <e-column field='TaskName' headerText= 'Task Name' width= 270></e-column>
                <e-column field= 'resources' headerText= 'Resources' width= 175>
                    <ng-template #template let-data>
                        <div *ngIf="data.ganttProperties.resourceNames">
                            <div [style]= "Resources(data.ganttProperties.resourceNames)">
                                <div [style]= "ResourcesStyles(data.ganttProperties.resourceNames)">  </div>
                            </div>
                        </div>
                    </ng-template>
                </e-column>
                <e-column field= 'StartDate' headerText='Start Date' width= 150 ></e-column>
                <e-column field= 'Duration' headerText='Duration' width= 150 ></e-column>
                <e-column field= 'Progress' headerText= 'Progress' width= 150 ></e-column>
            </e-columns>
        </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})

export class AppComponent implements OnInit {
    public data?: object[];
    public taskSettings?: object;
    public splitterSettings?: object;
    public resources?: object[];
    public resourceFields?: object;
    public style: any;
    public resourceStyleColor: any;
    public resourceContentStyle: any;

    public ngOnInit(): void {
        this.data = GanttData;
        this.resources = editingResources;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            resourceInfo: 'resources',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks',
        };
        this.splitterSettings = {
            columnIndex: 2
        };
        this.resourceFields = {
            id: 'resourceId',
            name: 'resourceName'
        };
    }


    public getResourceStyle(resource: { resourceId: number; resourceName: string }): string {
        switch (resource.resourceName) {
            case 'Martin Tamer':
                this.style = "display: flex; padding: 1.5px 12px; gap: 10px; width: 81px; height: 24px; border-radius: 24px; background: #DFECFF ";
                break;
            case 'Rose Fuller':
                this.style = "display: flex; padding: 1.5px 12px; gap: 10px; width: 71px; height: 24px; border-radius: 24px; background: #E4E4E7 ";
                break;
            case 'Margaret Buchanan':
                this.style = "display: flex; padding: 1.5px 12px; gap: 10px; width: 123px; height: 24px; border-radius: 24px; background: #DFFFE2 ";
                break;
            case 'Tamer Vinet':
                this.style = "display: flex; padding: 1.5px 12px; gap: 10px; width: 75px; height: 24px; border-radius: 24px; background: #FFEBE9 ";
                break;
        }
        return this.style;

    }

    public ResourcesStyles(resource: { resourceId: number; resourceName: string }): string {
        switch (resource.resourceName) {
            case 'Martin Tamer':
                this.style = "width: 72px; height: 22px; font-style: normal; font-weight: 500; font-size: 14px; line-height: 22px; text-align: center; color: #006AA6";
                break;
            case 'Rose Fuller':
                this.style = "width: 72px; height: 22px; font-style: normal; font-weight: 500; font-size: 14px; line-height: 22px; text-align: center; color: #766B7C";
                break;
            case 'Margaret Buchanan':
                this.style = "width: 72px; height: 22px; font-style: normal; font-weight: 500; font-size: 14px; line-height: 22px; text-align: center; color: #00A653";
                break;
            case 'Tamer Vinet':
                this.style = "width: 72px; height: 22px; font-style: normal; font-weight: 500; font-size: 14px; line-height: 22px; text-align: center; color: #FF3740";
                break;
        }
        return this.style;
    }

    public queryTaskbarInfo(args: IQueryTaskbarInfoEventArgs): void {
        const data = args.data as CustomGanttData;
        if (data.resources?.includes('Martin Tamer')) {
            args.taskbarBgColor = '#DFECFF';
            args.progressBarBgColor = '#006AA6';
        } else if (data.resources?.includes('Rose Fuller')) {
            args.taskbarBgColor = '#E4E4E7';
            args.progressBarBgColor = '#766B7C';
        } else if (data.resources?.includes('Margaret Buchanan')) {
            args.taskbarBgColor = '#DFFFE2';
            args.progressBarBgColor = '#00A653';
        } else if (data.resources?.includes('Tamer Vinet')) {
            args.taskbarBgColor = '#FFEBE9';
            args.progressBarBgColor = '#FF3740';
        }
    }

}

export interface CustomGanttData extends IGanttData {
    resources?: string[];
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
export let GanttData: Object[] = [
    {
        TaskID: 1,
        TaskName: 'Project Initiation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            {
                TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4,
                Progress: 30, resources: [1], info: 'Measure the total property area alloted for construction'
            },
            {
                TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Predecessor: '2',
                resources: [2], info: 'Obtain an engineered soil test of lot where construction is planned.' +
                    'From an engineer or company specializing in soil testing'
            },
            { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Predecessor: '3', Progress: 30, resources: [3], },
        ]
    },
    {
        TaskID: 5,
        TaskName: 'Project Estimation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
        subtasks: [
            {
                TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'),
                Duration: 3, Predecessor: '4', Progress: 30, resources: [4],
                info: 'Develop floor plans and obtain a materials list for estimations'
            },
            {
                TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'),
                Duration: 3, Predecessor: '6', resources: [1], info: ''
            },
            {
                TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'),
                Duration: 4, Predecessor: '7', resources: [2], info: ''
            }
        ]
    },
];

export let editingResources: Object[] = [
    { resourceId: 1, resourceName: 'Martin Tamer' },
    { resourceId: 2, resourceName: 'Rose Fuller' },
    { resourceId: 3, resourceName: 'Margaret Buchanan' },
    { resourceId: 4, resourceName: 'Tamer Vinet' },
];

This configuration applies background colors to resource columns and taskbars, with the queryTaskbarInfo event modifying taskbar properties dynamically.

See also