Task dependency or task relationship can be established between two tasks in Gantt. This dependency affects the project schedule. If you change the predecessor of a task, it will affect the successor task, which will affect the next task, and so on.
Task relationships are categorized into four types based on the start and finish dates of the task.
You cannot start a task until the dependent task also starts.
You cannot finish a task until the dependent task is started.
You cannot start a task until the dependent task is completed.
You cannot finish a task until the dependent task is completed.
Task relationship is defined in the data source as a string value, and this value is mapped to the Gantt control by using the TaskFields.Dependency
property. The following code example demonstrates how to enable the predecessor in the Gantt control.
@Html.EJS().Gantt("Gantt").DataSource((IEnumerable<object>)ViewBag.DataSource).Height("450px").TaskFields(ts =>
ts.Id("TaskId").Name("TaskName").StartDate("StartDate").EndDate("EndDate").Duration("Duration").Progress(
"Progress").Dependency("Predecessor").Child("SubTasks")).Render()
public IActionResult Index()
{
ViewBag.DataSource = ganttData();
return View();
}
public static List<GanttDataSource> ganttData()
{
List<GanttDataSource> GanttDataSourceCollection = new List<GanttDataSource>();
GanttDataSource Record1 = new GanttDataSource()
{
TaskId = 1,
TaskName = "Project initiation",
StartDate = new DateTime(2019, 04, 02),
EndDate = new DateTime(2019, 04, 21),
SubTasks = new List<GanttDataSource>(),
};
GanttDataSource Child1 = new GanttDataSource()
{
TaskId = 2,
TaskName = "Identify site location",
StartDate = new DateTime(2019, 04, 02),
Duration = 4,
Progress = 70,
};
GanttDataSource Child2 = new GanttDataSource()
{
TaskId = 3,
TaskName = "Perform soil test",
StartDate = new DateTime(2019, 04, 02),
Duration = 4,
Progress = 50,
Predecessor = "2FS"
};
GanttDataSource Child3 = new GanttDataSource()
{
TaskId = 4,
TaskName = "Soil test approval",
StartDate = new DateTime(2019, 04, 02),
Duration = 4,
Progress = 50,
Predecessor="3FS"
};
Record1.SubTasks.Add(Child1);
Record1.SubTasks.Add(Child2);
Record1.SubTasks.Add(Child3);
GanttDataSource Record2 = new GanttDataSource()
{
TaskId = 5,
TaskName = "Project estimation",
StartDate = new DateTime(2019, 04, 02),
EndDate = new DateTime(2019, 04, 21),
SubTasks = new List<GanttDataSource>()
};
GanttDataSource Child4 = new GanttDataSource()
{
TaskId = 6,
TaskName = "Develop floor plan for estimation",
StartDate = new DateTime(2019, 04, 04),
Duration = 3,
Progress = 70
};
GanttDataSource Child5 = new GanttDataSource()
{
TaskId = 7,
TaskName = "List materials",
StartDate = new DateTime(2019, 04, 04),
Duration = 3,
Progress = 50,
Predecessor = "6SS"
};
Record2.SubTasks.Add(Child4);
Record2.SubTasks.Add(Child5);
GanttDataSourceCollection.Add(Record1);
GanttDataSourceCollection.Add(Record2);
return GanttDataSourceCollection;
}
public class GanttDataSource
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public string Predecessor { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int? Duration { get; set; }
public int Progress { get; set; }
public List<GanttDataSource> SubTasks { get; set; }
}
The following screenshot displays the output of the above code.
In the Gantt control, the predecessor offset can be defined with the following duration units:
You can define an offset with various offset duration units for predecessors by using the following code example.
@Html.EJS().Gantt("Gantt").DataSource((IEnumerable<object>)ViewBag.DataSource).TaskFields(ts => ts.Id("TaskId").Name("TaskName").StartDate(
"StartDate").EndDate("EndDate").Duration("Duration").Progress("Progress").Dependency("Predecessor").Child("SubTasks")).Render()
public IActionResult Index()
{
ViewBag.DataSource = ProjectNewData();
return View();
}
public static List<GanttDataSource> ProjectNewData()
{
List<GanttDataSource> GanttDataSourceCollection = new List<GanttDataSource>();
GanttDataSource Record1 = new GanttDataSource()
{
TaskId = 1,
TaskName = "Product concept",
StartDate = new DateTime(2019, 04, 02),
EndDate = new DateTime(2019, 04, 21),
SubTasks = new List<GanttDataSource>(),
};
GanttDataSource Child1 = new GanttDataSource()
{
TaskId = 2,
TaskName = "Defining the product and its usage",
StartDate = new DateTime(2019, 04, 02),
Progress = 30,
Duration = 3,
};
GanttDataSource Child2 = new GanttDataSource()
{
TaskId = 3,
TaskName = "Defining target audience",
StartDate = new DateTime(2019, 04, 02),
Duration = 3,
Predecessor = "2FS+2d"
};
GanttDataSource Child3 = new GanttDataSource()
{
TaskId = 4,
TaskName = "Prepare product sketch and notes",
StartDate = new DateTime(2019, 04, 02),
Progress = 30,
Duration = 2,
Predecessor = "3FF+960m"
};
Record1.SubTasks.Add(Child1);
Record1.SubTasks.Add(Child2);
Record1.SubTasks.Add(Child3);
GanttDataSource Record2 = new GanttDataSource()
{
TaskId = 5,
TaskName = "Concept approval",
StartDate = new DateTime(2019, 04, 02),
Duration = 0,
SubTasks = new List<GanttDataSource>(),
};
GanttDataSource Child4 = new GanttDataSource()
{
TaskId = 6,
TaskName = "Demand analysis",
StartDate = new DateTime(2019, 04, 04),
EndDate = new DateTime(2019, 04, 21),
SubTasks = new List<GanttDataSource>(),
};
GanttDataSource Child5 = new GanttDataSource()
{
TaskId = 7,
TaskName = "Customer strength",
StartDate = new DateTime(2019, 04, 04),
Duration = 4,
Progress = 30,
Predecessor = "6SS+16h"
};
Record2.SubTasks.Add(Child4);
Record2.SubTasks.Add(Child5);
GanttDataSourceCollection.Add(Record1);
GanttDataSourceCollection.Add(Record2);
return GanttDataSourceCollection;
}
public class GanttDataSource
{
public int TaskId { get; set; }
public string TaskName { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int? Duration { get; set; }
public int Progress { get; set; }
public string Predecessor { get; set; }
public List<GanttDataSource> SubTasks { get; set; }
}
The following screen shot depicts the duration unit support in the predecessor offset.
In Gantt, task relationship link can be broken by editing the start date, end date and duration value of task. When the task relationship broken on any edit action. This can be handled in Gantt in two ways.
When the task relationship link is broken on any edit action, then the ActionBegin
event will be triggered with requestType
argument as validateLinkedTask
. You can validate the editing action within the actionBegin event using the validateMode
event argument. The validateMode
event argument has the following properties:
Argument | Default value | Description |
---|---|---|
args.validateMode.respectLink | false | In this validation mode, the predecessor links get high priority. With this mode enabled, when the successor task is moved before the predecessor task’s end date, the editing will be reverted, and dates will be validated based on the dependency links. |
args.validateMode.removeLink | false | In this validation mode, the taskbar editing gets high priority. For inappropriate task dates, the dependency links will be removed and tasks will be moved to the edited date. |
args.validateMode.preserveLinkWithEditing | true | In this validation mode, the taskbar editing will be considered along with the dependency links. This relationship will be maintained by updating the offset value of predecessors. |
By default, the preserveLinkWithEditing
validation mode will be enabled, so the predecessors are updated with offset values.
The following sample explains enabling the respectLink
validation mode while editing the linked tasks in the ActionBegin
event.
@Html.EJS().Gantt("Gantt").DataSource((IEnumerable<object>)ViewBag.DataSource).TaskFields(ts => ts.Id("TaskId").Name("TaskName").StartDate(
"StartDate").EndDate("EndDate").Duration("Duration").Progress("Progress").Dependency("Predecessor").Child("SubTasks")).EditSettings(es =>
es.AllowTaskbarEditing(true)).ActionBegin("actionBegin").Render()
<script>
function actionBegin(args) {
if (args.requestType == "validateLinkedTask") {
args.validateMode.respectLink = true;
}
}
</script>
public IActionResult Index()
{
ViewBag.DataSource = GanttData.ProjectNewData();
return View();
}
When disabling all the validation modes in the ActionBegin
event, a validation pop-up will be displayed prompting users to select the validation mode to validate taskbar editing.
This validation pop-up will display different options based on the successor task’s start date after editing.
If you move the successor task that starts after the predecessor task’s end date, then a dialog will be rendered with the following options:
If you move the successor task that starts before the predecessor task’s end date, then a dialog will be rendered with the following options:
The following code example shows how to enable the predecessor validation dialog in Gantt.
@Html.EJS().Gantt("Gantt").DataSource((IEnumerable<object>)ViewBag.DataSource).TaskFields(ts => ts.Id("TaskId").Name(
"TaskName").StartDate("StartDate").EndDate("EndDate").Duration("Duration").Progress("Progress").Dependency("Predecessor").Child("SubTasks")
).EditSettings(es => es.AllowTaskbarEditing(true)).ActionBegin("actionBegin").Render()
<script>
function actionBegin(args) {
if (args.requestType == "validateLinkedTask") {
args.validateMode.preserveLinkWithEditing = false;
}
}
</script>
public IActionResult Index()
{
ViewBag.DataSource = GanttData.ProjectNewData();
return View();
}
In this case, if the user dragging action violated the predecessor type then the following dialog will be rendered to perform operation.