Validation in Angular Gantt Chart Component

18 Nov 201824 minutes to read

Validation in the Angular Gantt Chart component ensures accurate task data by enforcing rules during adding or editing, preventing invalid entries before saving. Using the Form Validator component, apply validation to columns in inline or dialog editing, custom rules for specific fields, or dependency and resource grids in the add/edit dialog. Requires EditService and valid taskFields mappings (e.g., id, name) to ensure data integrity for tasks updated on September 23, 2025, or later, maintaining valid date ranges or dependency formats.

Validate columns

Define validation rules for columns using columns.validationRules, such as required or minLength, to display error messages for invalid fields like missing task names in inline or dialog editing.

import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { EditService, GanttModule, EditSettingsModel } from '@syncfusion/ej2-angular-gantt'

@Component({
    imports: [GanttModule],
    providers: [EditService],
    standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" height="430px" [dataSource]="data" [taskFields]="taskSettings" [toolbar]="toolbar" [editSettings]="editSettings" [columns]="columns"></ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})

export class AppComponent implements OnInit {
    public data?: object[];
    public taskSettings?: object;
    public columns?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: string[];

    public ngOnInit(): void {
        this.data = [
            {
                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: 50 },
                    { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                    { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                ]
            },
            {
                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, Progress: 50 },
                    { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                    { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
                ]
            },
        ];
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            endDate: 'EndDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
        this.editSettings = {
            allowAdding: true,
            allowEditing: true,
            allowDeleting: true,
            allowTaskbarEditing: true,
            showDeleteConfirmDialog: true
        };
        this.toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel'];
        this.columns = [
            { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '100' },
            { field: 'TaskName', headerText: 'Task Name', width: '250', validationRules: { required: true } },
            {
                field: 'StartDate', editType: 'datetimepickeredit', edit: { params: { format: 'M/d/y hh:mm a' } },
                format: { format: 'M/d/y hh:mm a', type: 'dateTime' }, validationRules: { required: true, date: true }
            },
            { field: 'Duration', headerText: 'Duration', width: '150', validationRules: { required: true } },
            { field: 'Progress', headerText: 'Progress', width: '150', validationRules: { required: true } },
        ];
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Apply custom validation

Implement custom validation for specific columns, like TaskName, using callback functions in columns.validationRules to enforce unique requirements, such as ensuring task names meet specific patterns.

import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { GanttModule, EditService, EditSettingsModel } from '@syncfusion/ej2-angular-gantt'

@Component({
    imports: [GanttModule],
    providers: [EditService],
    standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt height="430px" [dataSource]="data" [taskFields]="taskSettings" [toolbar]="toolbar" [editSettings]="editSettings" [columns]="columns"></ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent implements OnInit {
    public data?: object[];
    public taskSettings?: object;
    public columns?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: string[];
    public ngOnInit(): void {
        this.data = [
            {
                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: 50 },
                    { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                    { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                ]
            },
            {
                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, Progress: 50 },
                    { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                    { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
                ]
            },
        ];
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            endDate: 'EndDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
        this.editSettings = {
            allowAdding: true,
            allowEditing: true,
            allowDeleting: true,
            allowTaskbarEditing: true,
            showDeleteConfirmDialog: true
        };
        this.toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel'];
        this.columns = [
            { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '100' },
            { field: 'TaskName', headerText: 'Task Name', width: '250', validationRules: { required: true, minLength: [this.customFn, 'Value should be within 8 letters'] } },
            {
                field: 'StartDate', editType: 'datetimepickeredit', edit: { params: { format: 'M/d/y hh:mm a' } },
                format: { format: 'M/d/y hh:mm a', type: 'dateTime' }, validationRules: { required: true, date: true }
            },
            { field: 'Duration', headerText: 'Duration', width: '150', validationRules: { required: true } },
            { field: 'Progress', headerText: 'Progress', width: '150', validationRules: { required: true } },
        ];
    }

    public customFn: (args: { [key: string]: string }) => boolean = (args: { [key: string]: string }) => {
      return args['value'].length <= 8;
    };
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Validate dependency and resource grids

Set validation rules for dependency and resource grids in the add/edit dialog using the actionBegin event with requestType set to beforeOpenEditDialog or beforeOpenAddDialog, configuring validationRules for fields like predecessor types or resource assignments to ensure valid entries.

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

@Component({
    imports: [GanttModule],
    providers: [EditService],
    standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt height="430px" [dataSource]="data" [taskFields]="taskSettings" [toolbar]="toolbar" [editSettings]="editSettings" [resourceFields] = "resourceFields" 
       [resources]="resources" (actionBegin)="actionBegin($event)" [columns]="columns"></ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})

export class AppComponent implements OnInit {
    public data?: object[];
    public taskSettings?: object;
    public columns?: object[];
    public editSettings?: EditSettingsModel;
    public toolbar?: string[];
    public resourceFields?: object;
    public resources?: object[];

    public ngOnInit(): void {
        this.data = [
            {
                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: 50 },
                    { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                    { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
                ]
            },
            {
                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, Progress: 50 },
                    { TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
                    { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
                ]
            },
        ];
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            endDate: 'EndDate',
            duration: 'Duration',
            dependency: 'Predecessor',
            progress: 'Progress',
            child: 'subtasks',
            resourceInfo: 'resources'
        };
        this.resourceFields = {
            id: 'resourceId',
            name: 'resourceName'
        };
        this.resources = editingResources;
        this.editSettings = {
            allowAdding: true,
            allowEditing: true,
            allowDeleting: true,
            allowTaskbarEditing: true,
            showDeleteConfirmDialog: true
        };
        this.toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel'];
        this.columns = [
            { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '100' },
            { field: 'TaskName', headerText: 'Task Name', width: '250', validationRules: { required: true } },
            {
                field: 'StartDate', editType: 'datetimepickeredit', edit: { params: { format: 'M/d/y hh:mm a' } },
                format: { format: 'M/d/y hh:mm a', type: 'dateTime' }, validationRules: { required: true, date: true }
            },
            { field: 'Duration', headerText: 'Duration', width: '150', validationRules: { required: true } },
            { field: 'Progress', headerText: 'Progress', width: '150', validationRules: { required: true } },
        ];
    }

    public actionBegin(args: CustomDependencyEventArgs ): void {
        if (args.requestType == "beforeOpenEditDialog" || args.requestType == "beforeOpenAddDialog") {
            args.Dependency.columns[3].validationRules = { required: true };
            args.Resources.columns[2].allowEditing = true;
            args.Resources.columns[2].validationRules = { required: true };
        }
    }
}

interface Column {
    field?: string;
    headerText?: string;
    allowEditing?: boolean;
    validationRules?: { [key: string]: any };
    [key: string]: any;
}

interface CustomDependencyEventArgs extends IDependencyEventArgs {
    requestType: string;
    Dependency: {
        columns: Column[];
    };
    Resources: {
        columns: Column[];
    };
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

See also