DevExtreme v26.1 is now available.

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

Your search did not match any results.

Vue 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
<template> <div id="form-demo"> <div class="options"> <div class="caption">Options</div> <div class="option"> <DxCheckBox v-model:value="autoUpdateParentTasks" text="Auto Update Parent Tasks" /> </div> <div class="option"> <DxCheckBox v-model:value="validateDependencies" text="Enable Dependency Validation" /> </div> <div class="option"> <DxCheckBox v-model:value="enablePredecessorGap" text="Enable Predecessor Gap" /> </div> </div> <div class="widget-container"> <DxGantt :task-list-width="500" :height="700" task-title-position="none" > <DxValidation :auto-update-parent-tasks="autoUpdateParentTasks" :validate-dependencies="validateDependencies" :enable-predecessor-gap="enablePredecessorGap" /> <DxTasks :data-source="tasks"/> <DxDependencies :data-source="dependencies"/> <DxEditing :enabled="true"/> <DxColumn :width="300" data-field="title" caption="Task" /> <DxColumn data-field="start" caption="Start Date" /> <DxColumn data-field="end" caption="End Date" /> </DxGantt> </div> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; import { DxGantt, DxTasks, DxDependencies, DxColumn, DxEditing, DxValidation, } from 'devextreme-vue/gantt'; import DxCheckBox from 'devextreme-vue/check-box'; import { tasks, dependencies, } from './data.ts'; const autoUpdateParentTasks = ref(true); const validateDependencies = ref(true); const enablePredecessorGap = ref(true); </script> <style> .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: 44px; display: inline-block; } .option:last-child { margin-right: 0; } </style>
const currentDate = new Date(Date.now()); const month = currentDate.getMonth(); const year = currentDate.getFullYear(); export const tasks = [{ 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, }]; export const dependencies = [{ 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, }];
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
<!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" /> <link rel="stylesheet" type="text/css" href="./bundle.css" /> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"> </div> </div> <script src="bundles/vendor/vue.vendor.js"></script> <script src="./bundle.js"></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.