Resources in Angular Gantt Chart Component

24 Jul 202624 minutes to read

Resources in the Angular Gantt Chart 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]= "getResourceStyle(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.

Restrict resource selection to a single resource in the edit dialog

By default, the Resources tab in the Gantt edit dialog allows users to select multiple resources for a task. You can restrict resource assignment to a single resource by customizing the resource grid displayed in the edit dialog.

To achieve this requirement:

  • Remove the checkbox column from the Resources tab using the actionBegin event with the requestType of beforeOpenEditDialog.
  • Configure the resource grid selection behavior using the actionComplete event with requestType of openEditDialog by,
    • Setting checkboxOnly to false to allow row selection without requiring a checkbox click.
    • Setting the resource grid selection type to Single to allow only one resource selection at a time.
    • Disabling persistent selection by setting persistSelection to false.

The following example demonstrates how to restrict resource selection to a single resource in the Resources tab of the edit dialog. Additionally, a custom condition is applied to disable resource selection in the Resources tab when editing Task 3.

import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { GanttModule, EditService, SelectionService, SplitterSettingsModel, EditSettingsModel } from '@syncfusion/ej2-angular-gantt'
import { GanttData, ProjectResources } from './data';
import { Tab } from '@syncfusion/ej2-navigations';
import { Grid, SelectionSettingsModel } from '@syncfusion/ej2-grids';

@Component({
    imports: [GanttModule],
    providers:[EditService, SelectionService],
    standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt #gantt id="Gantt" height="450px" [dataSource]="data" [taskFields]="taskSettings" [splitterSettings]="splitterSettings" [treeColumnIndex]="1" [projectStartDate]="projectStartDate" [projectEndDate]="projectEndDate" [labelSettings]="labelSettings"
        (actionBegin)="actionBegin($event)" (actionComplete)="actionComplete($event)"
        [editDialogFields]="editDialogFields" [editSettings]="editSettings"
        [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 editDialogFields?: object[];
    public editSettings?: EditSettingsModel;
    public projectEndDate?: Date;
    public splitterSettings?: SplitterSettingsModel;
    public resourceFields?: object;
    public columns?: object[];

    public ngOnInit(): void {
        this.data = GanttData
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            endDate: 'EndDate',
            duration: 'Duration',
            progress: 'Progress',
            resourceInfo: 'resources',
            parentID: 'ParentID'
        };
        this.labelSettings = {
            leftLabel: 'TaskName',
            rightLabel: 'resources'
        };
        this.editDialogFields = [
            { type: 'Resources' }
        ];
        this.editSettings = {
            allowEditing: true
        };
        this.resourceFields = {
            id: 'resourceId',
            name: 'resourceName',
            unit: 'Unit'
        };
        this.columns = [
            { field: 'TaskID',  width: '70' },
            { field: 'TaskName', headerText: 'Task Name', width: '220' },
            { field: 'resources', headerText: 'Resources', width: '160' },
            { field: 'Duration', width: '100' }
        ];
        this.splitterSettings = {
            columnIndex: 3
        };
        this.projectStartDate = new Date('03/25/2019');
        this.projectEndDate = new Date('04/28/2019');
        this.resources = ProjectResources
    }

    public actionBegin(args: any) {
        if (args.requestType == 'beforeOpenEditDialog') {
            // Remove the checkbox column from the Resources tab.
            args.Resources.columns.splice(0, 1);
            // Disable resource selection for a specific task.
            if (args.rowData.TaskID == 3) {
                args.Resources.allowSelection = false;
            }
        }
    }

    public actionComplete(args: any) {
        if (args.requestType == 'openEditDialog') {
            // Get the Resources tab instance.
            let tabObj: Tab = (document.getElementById('Gantt_Tab') as any).ej2_instances[0];
            // Get the resource Grid instance from the Resources tab.
            let gridObj: Grid = (document.getElementById('GanttResourcesTabContainer_gridcontrol') as any).ej2_instances[0];
            // Configure the resource grid to allow only a single selection.
            gridObj.selectionSettings = {
                checkboxOnly: false,
                type: 'Single',
                persistSelection: false
            }  as SelectionSettingsModel;
        }
    }
}
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'),
    },
    { TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, ParentID:1, Progress: 90, resources: [{ resourceId: 2, resourceUnit: 50 }] },
    { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, ParentID:1, Progress: 40 },
    { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, ParentID:1, Progress: 10, resources: [{ resourceId: 3, resourceUnit: 100 }] },      
    {
        TaskID: 5,
        TaskName: 'Project Estimation',
        StartDate: new Date('04/02/2019'),
        EndDate: new Date('04/21/2019'),
    },
    { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, ParentID:5, Progress: 85, resources: [{ resourceId: 6, resourceUnit: 70 }] },
    { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, ParentID:5, Progress: 15, resources: [{ resourceId: 4, resourceUnit: 60 }] },
    { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, ParentID:5, Progress: 70, resources: [{ resourceId: 5, resourceUnit: 40 }] }
];

export let ProjectResources: object[] =  [
    { 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  },
];

With this configuration, users can assign only a single resource to a task through the Resources tab of the Gantt edit dialog.

See also