Search code examples
c#asp.net-mvckendo-uikendo-gridkendo-asp.net-mvc

How can I conditionally change the values of a dropdown in a Kendo Grid?


I'm developing a project with ASP MVC 5, Kendo UI, and some layers. The main idea is that after I chose a value from a dropdown column in a Kendo Grid for example:

columns.Bound(b => b.Country).ClientTemplate("#=Country.Name#");

It should update a second and third column based on the previous selection:

columns.Bound(b => b.Category).ClientTemplate("#=Category.Name#");
columns.Bound(b => b.Client).ClientTemplate("#=Client.Name#");

I haven't been able to find any example or idea in the Telerik documentation or forums:

Grid/Events

Grid / Editing custom editor

Refresh/Replace DataSource of Foreignkey DropDown List

I read this example too with a normal dropdown:

Kendo UI DropDownList on a change to trigger event

Has anyone experienced something like this? My current idea is to create N number of Editor Templates:

@model Kendo.Mvc.Examples.Models.CategoryViewModel

@(Html.Kendo().DropDownListFor(m => m)
    .DataValueField("CategoryID")
    .DataTextField("CategoryName")
    .BindTo((System.Collections.IEnumerable)ViewData["categories"])
)

With each of the possible Countries, however, it could be really inefficient and I still don't know how to trigger the on Change event.


Solution

  • After a long research, I was able to find a solution in this example:

    Grid InLine and PopUp Editing using Cascading DropDownLists

    However, it wasn't just copy and paste, I still don't know why this example is not available in the official FAQ Telerik page, but I'd like to provide the key point in order to do it:

    1) You must select the InLine or PopUp edit mode:

    .Editable(editable => editable.Mode(GridEditMode.InLine))
    

    Why? Because when you are going to edit or add the line:

    Image 1

    The cascade Drop downs are fully linked to the ID, for example: Image 2

    2) Next, your new column in the grid is going to look this one:

    columns.Bound(b => b.CategoryID).ClientTemplate("#=Category.Name#");
    

    Be careful, before I we used the class as Category instead of the CategoryID, the ID is the crucial point.

    3) You need to change the previous approach from adding the hint to the class to the ID of the it, for example:

    Non-cascade approach:

    [UIHint("ClientStatus")]
    public Statuses Status { get; set; }
    
    public int StatusID { get; set; }
    

    Cascade approach:

    public Statuses Status { get; set; }
    
    [UIHint("ClientStatus")]
    public int StatusID { get; set; }
    

    3) The editor template from the cascade approaches should look like this:

    Basic one:

    @model int
    
    @(Html.Kendo().DropDownListFor(m => m)
            .AutoBind(false)
            .DataValueField("CategoriesID")
            .DataTextField("Name")
            .DataSource(dataSource =>
            {
                dataSource.Read(read => read.Action("PopulateCategories", "FullView"))
                .ServerFiltering(true);
            })
    )
    @Html.ValidationMessageFor(m => m)
    

    Cascade ones:

    @model int
    
    @(Html.Kendo().DropDownListFor(m => m)
            .AutoBind(false)
            .DataValueField("ID")
            .DataTextField("Name")
            .DataSource(dataSource =>
            {
                dataSource.Read(read => read.Action("PopulateStatuses", "FullView").Data("filterCategories"))
                .ServerFiltering(true);
            })
            .CascadeFrom("CategoriesID")
    )
    @Html.ValidationMessageFor(m => m)
    

    4) The cascade is calling a JavaScript function that looks like this:

    function filterCategories() {
        return {
            categoriesID: $("#CategoriesID").data("kendoDropDownList").value()
        };
    }
    

    Where CategoriesID is the ID of the first drop down, which is generated when we edit or add a new line.

    4) Finally, we need to share a JSON as a result:

    First drop down:

    public JsonResult PopulateCategories()
    {
            return Json(CategoriesData.GetCategories(), JsonRequestBehavior.AllowGet);
    }
    

    Second and further drop downs:

    public JsonResult PopulateStatuses(int categoryID)
    {
            return Json(StatusesData.GetStatuses(categoryID), JsonRequestBehavior.AllowGet);
    }