DevExtreme v26.1 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Angular Gantt - Validation

The DevExtreme Gantt component allows you to validate relationships between tasks and handle errors. Set the enableDependencyValidation property to true to enable task validation.

Backend API
<div id="demo-container"> <div class="options"> <div class="caption">Options</div> <div class="option"> <dx-check-box text="Auto Update Parent Tasks" [(value)]="autoUpdateParentTasks" ></dx-check-box> </div> <div class="option"> <dx-check-box text="Enable Dependency Validation" [(value)]="validateDependencies" ></dx-check-box> </div> <div class="option"> <dx-check-box text="Enable Predecessor Gap" [(value)]="enablePredecessorGap" ></dx-check-box> </div> </div> <div class="widget-container"> <dx-gantt taskListWidth="500" height="700" taskTitlePosition="none"> <dxo-gantt-validation [autoUpdateParentTasks]="autoUpdateParentTasks" [validateDependencies]="validateDependencies" [enablePredecessorGap]="enablePredecessorGap" ></dxo-gantt-validation> <dxo-gantt-tasks [dataSource]="tasks"></dxo-gantt-tasks> <dxo-gantt-dependencies [dataSource]="dependencies" ></dxo-gantt-dependencies> <dxi-gantt-column dataField="title" caption="Task" [width]="300" ></dxi-gantt-column> <dxi-gantt-column dataField="start" caption="Start Date" dataType="date" ></dxi-gantt-column> <dxi-gantt-column dataField="end" caption="End Date" dataType="date" ></dxi-gantt-column> <dxo-gantt-editing [enabled]="true"></dxo-gantt-editing> </dx-gantt> </div> </div>
import { bootstrapApplication } from '@angular/platform-browser'; import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core'; import { DxGanttModule, DxCheckBoxModule } from 'devextreme-angular'; import { Service, Task, Dependency } from './app.service'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [Service], preserveWhitespaces: true, imports: [ DxGanttModule, DxCheckBoxModule, ], }) export class AppComponent { tasks: Task[]; dependencies: Dependency[]; autoUpdateParentTasks: boolean; validateDependencies: boolean; enablePredecessorGap: boolean; constructor(service: Service) { this.tasks = service.getTasks(); this.dependencies = service.getDependencies(); this.autoUpdateParentTasks = true; this.validateDependencies = true; this.enablePredecessorGap = true; } } bootstrapApplication(AppComponent, { providers: [ provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }), ], });
#gantt { height: 700px; } .options { margin-bottom: 20px; padding: 20px; background-color: rgba(191, 191, 191, 0.15); position: relative; } .caption { font-size: 18px; font-weight: 500; } .option { margin-top: 10px; margin-right: 40px; display: inline-block; } .option:last-child { margin-right: 0; }
import { Injectable } from '@angular/core'; export class Task { id: number; parentId: number; title: string; start: Date; end: Date; progress: number; } export class Dependency { id: number; predecessorId: number; successorId: number; type: number; } const currentDate: Date = new Date(Date.now()); const month: number = currentDate.getMonth(); const year: number = currentDate.getFullYear(); const tasks: Task[] = [{ id: 1, parentId: 0, title: 'Johnson Residence Construction Project', start: new Date(year, month - 1, 1), end: new Date(year, month - 1, 1), progress: 0, }, { id: 2, parentId: 1, title: 'Planning and Pre-Construction Phase', start: new Date(year, month - 1, 1), end: new Date(year, month - 1, 1), progress: 0, }, { id: 3, parentId: 2, title: 'Architectural Design and Site Planning', start: new Date(year, month - 1, 1), end: new Date(year, month - 1, 15), progress: 0, }, { id: 4, parentId: 2, title: 'Engineering and Final Blueprint', start: new Date(year, month - 1, 8), end: new Date(year, month - 1, 15), progress: 0, }, { id: 5, parentId: 2, title: 'City Permits and Contracts', start: new Date(year, month - 1, 15), end: new Date(year, month - 1, 18), progress: 0, }, { id: 6, parentId: 1, title: 'Construction Phase', start: new Date(year, month - 1, 18), end: new Date(year, month - 1, 18), progress: 0, }, { id: 7, parentId: 6, title: 'Grading and Excavation', start: new Date(year, month - 1, 18), end: new Date(year, month - 1, 22), progress: 0, }, { id: 8, parentId: 6, title: 'Demolition and Removal', start: new Date(year, month - 1, 19), end: new Date(year, month - 1, 23), progress: 0, }, { id: 9, parentId: 6, title: 'Foundation and Concrete ', start: new Date(year, month - 1, 22), end: new Date(year, month - 1, 28), progress: 0, }, { id: 10, parentId: 6, title: 'Rough Framing and Carpentery', start: new Date(year, month - 1, 25), end: new Date(year, month, 5), progress: 0, }, { id: 11, parentId: 6, title: 'Inspection (Structure)', start: new Date(year, month, 5), end: new Date(year, month, 5), progress: 0, }, { id: 12, parentId: 6, title: 'Electrical Rough-in', start: new Date(year, month, 6), end: new Date(year, month, 19), progress: 0, }, { id: 13, parentId: 6, title: 'Plumbing Rough-in', start: new Date(year, month, 19), end: new Date(year, month, 19), progress: 0, }, { id: 14, parentId: 6, title: 'Heating and A/C', start: new Date(year, month, 19), end: new Date(year, month, 26), progress: 0, }, { id: 15, parentId: 6, title: 'Drywall', start: new Date(year, month, 25), end: new Date(year, month + 1, 10), progress: 0, }, { id: 16, parentId: 6, title: 'Painting (Exterior)', start: new Date(year, month + 1, 7), end: new Date(year, month + 1, 21), progress: 0, }, { id: 17, parentId: 6, title: 'Interior Carpentery (Interior)', start: new Date(year, month + 1, 17), end: new Date(year, month + 1, 28), progress: 0, }, { id: 18, parentId: 6, title: 'Flooring and Interior Paint', start: new Date(year, month + 1, 26), end: new Date(year, month + 2, 9), progress: 0, }, { id: 19, parentId: 1, title: 'Final Phase', start: new Date(year, month + 2, 9), end: new Date(year, month + 2, 9), progress: 0, }, { id: 20, parentId: 19, title: 'Review-Punch List', start: new Date(year, month + 2, 9), end: new Date(year, month + 2, 23), progress: 0, }, { id: 21, parentId: 19, title: 'Final Inspection', start: new Date(year, month + 2, 24), end: new Date(year, month + 2, 24), progress: 0, }, { id: 22, parentId: 19, title: 'Final Paperwork and Documents', start: new Date(year, month + 2, 24), end: new Date(year, month + 2, 28), progress: 0, }]; const dependencies: Dependency[] = [{ id: 1, predecessorId: 4, successorId: 5, type: 0, }, { id: 2, predecessorId: 5, successorId: 7, type: 0, }, { id: 3, predecessorId: 12, successorId: 13, type: 0, }, { id: 4, predecessorId: 13, successorId: 14, type: 0, }, { id: 5, predecessorId: 18, successorId: 20, type: 0, }, { id: 6, predecessorId: 21, successorId: 22, type: 0, }]; @Injectable() export class Service { getTasks(): Task[] { return tasks; } getDependencies(): Dependency[] { return dependencies; } }
<!DOCTYPE html> <html lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/26.1.5/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/26.1.5/css/dx-gantt.css" /> </head> <body class="dx-viewport"> <div class="demo-container"> <demo-app>Loading...</demo-app> </div> <script src="https://cdn.jsdelivr.net/npm/zone.js@0.16.2/bundles/zone.umd.js"></script> <script src="./bundle.js" type="module"></script> </body> </html>

The Gantt supports the following dependency validation rules:

  • Finish to Start (FS) - A successor task's start point should be equal or later than the preceding task's end point.
  • Start to Start (SS) - A successor task's start point should be equal or later than the preceding task's start point.
  • Finish to Finish (FF) - A successor task's end point should be equal or later than the preceding task's end point.
  • Start to Finish (SF) - A successor task's end point should be equal or later than a preceding task's start point.

The Gantt also has the autoUpdateParentTasks property that enables validation for parent-child relationship:

  • A parent task's duration equals a summary duration of its child tasks.
  • A parent task and its first child starts at the same time.
  • A parent task and its last child ends at the same time.
  • A parent task's progress is a summary progress of its child tasks.

The Gantt processes changes in task values before they are saved to a database. The component displays a popup window with a list of available actions if an error can be handled in several ways.