New to Telerik UI for ASP.NET AJAX? Download free 30-day trial

Custom task edit window

Environment

Product Telerik WebForms Gantt for ASP.NET AJAX

Description

This example demonstrates how to create a custom task edit window with RadWindow, which will replace the default one when editing the Gantt's tasks.

Solution

The idea is to implement the Window in such a way it allows users to edit task details such as title, start date, end date, and completion percentage. It utilizes client-side JavaScript functions to handle events like double-clicking on a task, saving edits, validating start and end dates, and deleting tasks.

The editor window is displayed within a RadWindow component and interacts with the RadGantt control to update task information.

<telerik:RadGantt
    runat="server"
    RenderMode="Lightweight"
    SnapToGrid="false"
    ID="RadGantt1"
    AutoGenerateColumns="true"
    Height="500"
    SelectedView="MonthView"
    AllowColumnResize="true"
    OnTaskInsert="RadGantt1_TaskInsert" />

<telerik:RadWindow
    ID="RadWindow2"
    RenderMode="Lightweight"
    EnableShadow="true"
    Behaviors="Close, Move, Resize,Maximize"
    RestrictionZoneID="RestrictionZone"
    Title="Edit Task"
    runat="server"
    Width="360px"
    Height="440px"
    VisibleStatusbar="False">
    <ContentTemplate>
        <br />
        <%--ID--%>
        <div style="text-align: right; float: left">
            <asp:Label ID="Label1" Text="ID" runat="server" Width="85px" />
        </div>
        <div style="float: left; padding-left: 5px;">
            <asp:TextBox ID="TextBox1" runat="server" Width="220px" ReadOnly="True">
            </asp:TextBox>
        </div>

        <%--Divider Bar--%>
        <div style="border-bottom: thin solid #62676b; width: 325px; float: left; clear: left; padding-top: 12px">
        </div>

        <%--Title--%>
        <div style="text-align: right; float: left; padding-top: 12px;">
            <asp:Label ID="Label2" Text="Title" runat="server" Width="85px" />
        </div>
        <div style="float: left; padding-left: 5px; padding-top: 12px;">
            <asp:TextBox ID="TextBox2" runat="server" Width="220px">
            </asp:TextBox>
        </div>

        <%--Start--%>
        <div style="text-align: right; float: left; padding-top: 8px;">
            <asp:Label ID="Label3" Text="Start" runat="server" Width="85px" />
        </div>
        <div style="float: left; padding-left: 5px; padding-top: 8px;">
            <telerik:RadDateTimePicker ID="RadDatePicker1" Width="225px" runat="server">
                <DateInput runat="server" DateFormat="yyyy/M/d HH:mm" DisplayDateFormat="yyyy/M/d HH:mm"></DateInput>
            </telerik:RadDateTimePicker>
        </div>
        <div style="text-align: center; padding-left: 5px; padding-top: 8px;">
            <asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1" ControlToValidate="RadDatePicker1"
                ErrorMessage="Start date is required!" ForeColor="Red"></asp:RequiredFieldValidator>
        </div>

        <%--End--%>
        <div style="text-align: right; float: left; padding-top: 8px;">
            <asp:Label ID="Label4" Text="End" runat="server" Width="85px" />
        </div>
        <div style="float: left; padding-left: 5px; padding-top: 8px;">
            <telerik:RadDateTimePicker ID="RadDatePicker2" Width="225px" runat="server">
                <DateInput runat="server" DateFormat="yyyy/M/d HH:mm" DisplayDateFormat="yyyy/M/d HH:mm"></DateInput>
            </telerik:RadDateTimePicker>
        </div>
        <div style="text-align: center; padding-left: 5px; padding-top: 8px;">
            <asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator2" ControlToValidate="RadDatePicker2"
                ErrorMessage="End date is required!" ForeColor="Red"></asp:RequiredFieldValidator>
        </div>
        <div style="text-align: right; float: left; padding-top: 8px;">
            <span>
                <asp:CustomValidator ID="dateCompareValidator" EnableClientScript="true" runat="server"
                    ControlToValidate="RadDatePicker2" ClientValidationFunction="validateStartEndDate"
                    ErrorMessage="End date should be after or equal to the start date!" ForeColor="Red">
                </asp:CustomValidator>
            </span>
        </div>

        <%--Complete--%>
        <div style="text-align: right; float: left; padding-top: 8px;">
            <asp:Label ID="Label5" Text="Complete" runat="server" Width="85px" />
        </div>
        <div style="float: left; padding-left: 5px; padding-top: 8px;">
            <telerik:RadNumericTextBox runat="server" ID="TextBox3" Width="225" ShowSpinButtons="true"
                IncrementSettings-Step="0.01" Type="Number" MinValue="0" MaxValue="1" NumberFormat-DecimalSeparato=",">
            </telerik:RadNumericTextBox>
        </div>

        <%--Divider Bar--%>
        <div style="border-bottom: thin solid #62676b; width: 325px; float: left; clear: left; padding-top: 12px">
        </div>

        <%--Save Button--%>
        <div style="float: left; padding-left: 25px; padding-top: 12px;">
            <telerik:RadButton ID="RadButton1" runat="server" Text="Save" AutoPostBack="false" OnClientClicking="OnClientSaveClicking"></telerik:RadButton>
        </div>

        <%--Cancel Button--%>
        <div style="float: left; padding-left: 10px; padding-top: 12px;">
            <telerik:RadButton ID="RadButton2" runat="server" Text="Cancel" AutoPostBack="false" OnClientClicked="OnClientCancelClicked"></telerik:RadButton>
        </div>

        <%--Delete Button--%>
        <div style="float: left; padding-left: 10px; padding-top: 12px;">
            <telerik:RadButton ID="RadButton3" runat="server" Text="Delete" AutoPostBack="false" OnClientClicked="OnClientDeleteClicked"></telerik:RadButton>
        </div>

        <asp:HiddenField runat="server" ID="UidHiddenField" />
        <%--</div>--%>
    </ContentTemplate>
</telerik:RadWindow>
private const string ProviderSessionKey = "RadGanttResizingColumns";

public XmlGanttProvider Provider
{
    get
    {
        XmlGanttProvider provider = (XmlGanttProvider) Session[ProviderSessionKey];
        if (Session[ProviderSessionKey] == null || !IsPostBack)
        {
            provider = new XmlGanttProvider(Server.MapPath("~/App_Data/Tasks.xml"), false);

            Session[ProviderSessionKey] = provider;
        }

        return provider;
    }
}

protected void RadGantt1_TaskInsert(object sender, TaskEventArgs e)
{

}

private void Page_Init(object sender, EventArgs e)
{
    RadGantt1.Provider = Provider;
}
var $ = $ || $telerik.$;

function getTaskByUid(uid) {
    var gantt = $find("<%= RadGantt1.ClientID %>");
    var tasks = gantt.get_allTasks();

    for (var i = 0; i < tasks.length; i++) {
        if (tasks[i]._uid === uid) {
            return tasks[i];
            break;
        }
    }

    return null;
}

function getTaskById(id) {
    var gantt = $find("<%= RadGantt1.ClientID %>");
    var tasks = gantt.get_allTasks();

    for (var i = 0; i < tasks.length; i++) {
        if (tasks[i].get_id() === id) {
            return tasks[i];
            break;
        }
    }

    return null;
}

function pageLoadHandler() {
    var gantt = $find("<%= RadGantt1.ClientID %>");
    $(gantt.get_element()).find(".rgtTimelineContent").on("dblclick", ".rgtTask", function (e) {
        e.stopPropagation();
        var $element = $(e.target);

        if (!$element.is(".rgtTask")) {
            $element = $element.parents(".rgtTask").first();
        }

        var task = getTaskByUid($element.attr("data-uid"));
        showDialog(task);
    });
    // Sys.Application.remove_load(pageLoadHandler);  
}
Sys.Application.add_load(pageLoadHandler);

function showDialog(task) {
    var wnd = $find("<%= RadWindow2.ClientID%>");
    wnd.show();

    $get("<%=UidHiddenField.ClientID %>").value = task._uid;

    $get("<%=TextBox1.ClientID %>").value = task.get_id();
    $get("<%=TextBox2.ClientID %>").value = task.get_title();

    $find("<%=RadDatePicker1.DateInput.ClientID %>").set_value(task.get_start());
    $find("<%=RadDatePicker2.DateInput.ClientID %>").set_value(task.get_end());

    $get("<%=TextBox3.ClientID %>").value = task.get_percentComplete();
}

function OnClientSaveClicking(sender, args) {
    var isValid = Page_ClientValidate();
    if (!isValid) {
        args.set_cancel(true);
    }
    else {
        var uidValue = $get("<%=UidHiddenField.ClientID %>").value;

        var titleFieldValue = $get("<%=TextBox2.ClientID %>").value;
        var startDatePicker = $find("<%=RadDatePicker1.DateInput.ClientID %>");
        var endDatePicker = $find("<%=RadDatePicker2.DateInput.ClientID %>");

        var startFieldValue = startDatePicker.get_value();
        var endFieldValue = endDatePicker.get_value();

        var percentCompleteFieldValue = $get("<%=TextBox3.ClientID %>").value;

        var newStartDate = new Date(Date.parse(startFieldValue, startDatePicker.get_dateFormat()));
        var newEndDate = new Date(Date.parse(endFieldValue, endDatePicker.get_dateFormat()));

        var newPercentComplete = parseFloat(percentCompleteFieldValue.replace(",", "."));

        var task = getTaskByUid(uidValue);
        task.set_title(titleFieldValue);
        task.set_start(newStartDate);
        task.set_end(newEndDate);
        task.set_percentComplete(newPercentComplete);
        $find("<%= RadWindow2.ClientID%>").close();
    }
}

function validateStartEndDate(sender, args) {
    var RadDatePicker1 = $find("<%= RadDatePicker1.ClientID%>")
    var RadDatePicker2 = $find("<%= RadDatePicker2.ClientID%>")
    var Date1 = new Date(RadDatePicker1.get_selectedDate());
    var Date2 = new Date(RadDatePicker2.get_selectedDate());

    if ((Date2 - Date1) < 0) {
        args.IsValid = false;
    }
}

function OnClientCancelClicked(sender) {
    $find("<%= RadWindow2.ClientID%>").close();
}

function OnClientDeleteClicked(sender) {
    var uidValue = $get("<%=UidHiddenField.ClientID %>").value;
    var task = getTaskByUid(uidValue);
    var parentTaskId = task.get_parentId();

    if (parentTaskId) {
        var parentTask = getTaskById(parentTaskId);
        parentTask.get_tasks().remove(task);
    }
    else {
        var gantt = $find("<%= RadGantt1.ClientID %>");
        gantt.get_tasks().remove(task);
    }

    $find("<%= RadWindow2.ClientID%>").close();
}
<?xml version="1.0" encoding="utf-8"?>
<Project>
    <Tasks>
        <Task>
            <ID>1</ID>
            <ParentID />
            <Start>2014-05-05T08:00:00Z</Start>
            <End>2014-05-16T20:00:00Z</End>
            <Title>Defining selection criteria</Title>
            <PercentComplete>0.39</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>0</OrderID>
        </Task>
        <NextID>12</NextID>
        <Task>
            <ID>2</ID>
            <ParentID>5</ParentID>
            <Start>2014-05-19T08:00:00Z</Start>
            <End>2014-06-03T20:00:00Z</End>
            <Title>Advertising the position</Title>
            <PercentComplete>1</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>0</OrderID>
        </Task>
        <Task>
            <ID>3</ID>
            <ParentID>5</ParentID>
            <Start>2014-05-19T08:00:00Z</Start>
            <End>2014-06-03T20:00:00Z</End>
            <Title>Collecting job applications</Title>
            <PercentComplete>0.5</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>1</OrderID>
        </Task>
        <Task>
            <ID>4</ID>
            <ParentID />
            <Start>2014-06-04T08:00:00Z</Start>
            <End>2014-06-20T20:00:00Z</End>
            <Title>Categorizing applications</Title>
            <PercentComplete>0.5</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>2</OrderID>
        </Task>
        <Task>
            <ID>5</ID>
            <ParentID />
            <Start>2014-05-19T08:00:00Z</Start>
            <End>2014-06-03T20:00:00Z</End>
            <Title>Researching the market for candidates</Title>
            <PercentComplete>0.75</PercentComplete>
            <Summary>true</Summary>
            <Expanded>true</Expanded>
            <OrderID>1</OrderID>
        </Task>
        <Task>
            <ID>6</ID>
            <ParentID />
            <Start>2014-06-23T08:00:00Z</Start>
            <End>2014-08-06T08:00:00Z</End>
            <Title>Assessing applicants</Title>
            <PercentComplete>0.19333333333333336</PercentComplete>
            <Summary>true</Summary>
            <Expanded>true</Expanded>
            <OrderID>3</OrderID>
        </Task>
        <Task>
            <ID>7</ID>
            <ParentID>6</ParentID>
            <Start>2014-06-23T08:00:00Z</Start>
            <End>2014-07-11T20:00:00Z</End>
            <Title>Interview with Human Resources representatives</Title>
            <PercentComplete>0.24</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>0</OrderID>
        </Task>
        <Task>
            <ID>8</ID>
            <ParentID>6</ParentID>
            <Start>2014-07-14T08:00:00Z</Start>
            <End>2014-07-25T08:00:00Z</End>
            <Title>Asigning and reviewing a sample test task</Title>
            <PercentComplete>0.34</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>1</OrderID>
        </Task>
        <Task>
            <ID>9</ID>
            <ParentID>6</ParentID>
            <Start>2014-07-28T08:00:00Z</Start>
            <End>2014-08-06T08:00:00Z</End>
            <Title>Interview with Development Team representatives</Title>
            <PercentComplete>0</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>2</OrderID>
        </Task>
        <Task>
            <ID>10</ID>
            <ParentID />
            <Start>2014-08-06T08:00:00Z</Start>
            <End>2014-08-15T20:00:00Z</End>
            <Title>Creating and proposing the job offer</Title>
            <PercentComplete>0</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>4</OrderID>
        </Task>
        <Task>
            <ID>11</ID>
            <ParentID />
            <Start>2014-08-18T08:00:00Z</Start>
            <End>2014-08-22T14:00:00Z</End>
            <Title>Hiring applicant</Title>
            <PercentComplete>0</PercentComplete>
            <Summary>false</Summary>
            <Expanded>true</Expanded>
            <OrderID>5</OrderID>
        </Task>
    </Tasks>
    <Dependencies>
        <Dependency>
            <ID>1</ID>
            <PredecessorID>1</PredecessorID>
            <SuccessorID>2</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <NextID>12</NextID>
        <Dependency>
            <ID>2</ID>
            <PredecessorID>1</PredecessorID>
            <SuccessorID>3</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <Dependency>
            <ID>5</ID>
            <PredecessorID>2</PredecessorID>
            <SuccessorID>3</SuccessorID>
            <Type>FinishFinish</Type>
        </Dependency>
        <Dependency>
            <ID>6</ID>
            <PredecessorID>3</PredecessorID>
            <SuccessorID>4</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <Dependency>
            <ID>7</ID>
            <PredecessorID>4</PredecessorID>
            <SuccessorID>7</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <Dependency>
            <ID>8</ID>
            <PredecessorID>7</PredecessorID>
            <SuccessorID>8</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <Dependency>
            <ID>9</ID>
            <PredecessorID>8</PredecessorID>
            <SuccessorID>9</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <Dependency>
            <ID>10</ID>
            <PredecessorID>9</PredecessorID>
            <SuccessorID>10</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
        <Dependency>
            <ID>11</ID>
            <PredecessorID>10</PredecessorID>
            <SuccessorID>11</SuccessorID>
            <Type>FinishStart</Type>
        </Dependency>
    </Dependencies>
</Project>
In this article