passing value of kendo DropDownListFor to read action of another DropDownListFor

Matt Kagan picture Matt Kagan · Sep 4, 2014 · Viewed 7.2k times · Source

I have a DropDownListFor component which has a read action which gets values from the database. However, I want to filter those values based on the value of another DropDownListFor.

Here's the DropDownListFor component that has the filter value

        <div class="editor-field">
                        @(Html.Kendo().DropDownListFor(model => model.ReleaseID)
                        .DataTextField("Value")
                        .DataValueField("Key")
                        .DataSource(ds => ds 
                            .Read(read=>read.Action("GetReleases", "Task"))
                            ) 
                        ) 
            @Html.ValidationMessageFor(model => model.ReleaseID)
          </div>

What I want to do is pass the value of ReleaseID into the read action of another DropDownListFor. I tried to do it like this:

                <div class="editor-field">
                @(Html.Kendo().DropDownListFor(model => model.MarketModelID)
                      .Events(e => e.Select("onSelectMarketModel"))
                      .Template("<span data-title='Model Description: #: data.Item3 #'>#: data.Item2 # </span>")
                      .DataTextField("Item2")
                      .DataValueField("Item1")
                      .DataSource(ds => ds
                          .Read(read => read.Action("GetMarketModels", "Task", new { release = Model.ReleaseID }))
                  )) 
                @Html.ValidationMessageFor(model => model.MarketModelID)
            </div>

with the controller method signature:

public JsonResult GetMarketModels(int? release)
{
    //code to get market models based on release
}

However, the release in GetMarketModels method is always 0 no matter what the selection is for the ReleaseID DropDownFor at the top. What am I doing wrong?

Thank you.

Answer

vapcguy picture vapcguy · Oct 24, 2014

I don't really like the example, so I thought I'd spell out how you'd go from what you have, to what should work - both for my own benefit, yours, and others reading this:

First, you need a Name attribute on ReleaseID:

@(Html.Kendo().DropDownListFor(model => model.ReleaseID)
    .Name("ReleaseID")  // <-- needs this line added
    .DataTextField("Value")
    .DataValueField("Key")
    .DataSource(ds => ds 
        .Read(read=>read.Action("GetReleases", "Task"))
     ) 
 ) 

Next, you need to put in .Data(), specify a function that gives you the ReleaseID, indicate you are doing .ServerFiltering(true) and a .Cascade from your other dropdown, and create the function you specified to return, in Json format, the release ID to be used in the cascade:

@(Html.Kendo().DropDownListFor(model => model.MarketModelID)
    .Events(e => e.Select("onSelectMarketModel"))
    .Template("<span data-title='Model Description: #: data.Item3 #'>#: data.Item2 # </span>")
    .DataTextField("Item2")
    .DataValueField("Item1")
    .DataSource(source => 
    {
         source.Read(read => 
         {
             read.Action("GetMarketModels", "Task").Data("filterMarket");
         })
         .ServerFiltering(true);
     })
     .CascadeFrom("ReleaseID")  // <-- "Name" attribute, from above
     .Value(Model.MarketModelID != null ? Model.MarketModelID.ToString() : "1")
)
<script>
    function filterMarket() {
        return {
            strReleaseID : $("#ReleaseID").val()
        }
    }
</script>

Then, in your Task controller, you pass in your variable:

public JsonResult GetMarketModels(string strReleaseID)
{
    int releaseID = int.Parse(strReleaseID);
    var data = db.MarketModels.Where(t => t.ReleaseID == releaseID).ToList();
    return Json(data, JsonRequestBehavior.AllowGet);
}

Note that the name you gave the parameter in the JavaScript must match the name in the controller function. This method is what I've used to cascade dropdowns in an application and works for me.