How to create cascading drop-down list

The idea of cascading drop-down is, you select a value in the first drop-down, and it triggers some action to load the options for a second drop-down. A classic example is Country drop-down down and State drop-down. Every time user selects a country the country drop-down should be updated with the states under that country.

I am going to give you a very generic example of the Country-State use case. You can use the same concepts to build your specific use case

To start with , create a view model for your view. Create a property of type List<SelectListItem> for passing the list of options needed for building the SELECT element and another property to store the selected option value. We will do this for both the SELECT elements.

public class CreateUserVm
{
   public List<SelectListItem> Countries { set;get;}
   public int SelectedCountryId { set;get;}

   public List<SelectListItem> States { set;get;}
   public int SelectedStateId { set;get;}  

   public CreateUserVm()
   {
     this.Countries = new List<SelectListItem>();
     this.States = new List<SelectListItem>();
   }  
}

Now in your GET action method, create an object of this view model, initialize the options for the first dropdown , in this case the Countries property and send that to the view.

public ActionResult Create()
{ 
    var vm=new CreateUserVm();
    vm.Countries = GetCountries();
    return View(vm);
}
private List<SelectListItem> GetCountries()
{
    var list = new List<SelectListItem>
    {
        new SelectListItem() {Value = "1", Text = "USA"},
        new SelectListItem() {Value = "2", Text = "India"},
    };
    return list;
}

Now in your View, which is strongly typed to our view model. we will use the DropDownListFor helper method to render the drop-downs

@model CreateUserVm
@using (Html.BeginForm("Index", "Home"))
{
   @Html.DropDownListFor(a=>a.SelectedCountryId,Model.Countries,"Select one")
   @Html.DropDownListFor(a => a.SelectedStateId, Model.States, "Select one",
                                              new { data_url = Url.Action("GetStates") })
   <input type="Submit" />
}

This will render 2 dropdowns, one with Country options and the second one will be empty (because we did not load anything to the States property). Now we will have some javascript(we are using jquery here for easy DOM manipulation) which will listen to the change event of the first drop-down(Country) ,read the selected value and make an ajax call to the GetStates method and passing the selected country option value.

You can see that , i set a html5 data attribute for the second dropdown where i am storing the url to the GetStates method. So in my javascript, i can simply read this data attribute value and make a call to that url to get the data.

$(function () {
    $("#SelectedCountryId").change(function () {
        var v = $(this).val();
        var url = $("#SelectedStateId").data("url") + '?countryId=' + v;
        var $states = $("#SelectedStateId");
        $.getJSON(url, function (states) {
                $states.empty();
                $.each(states, function (i, item) {
                    $states.append($("<option>").text(item.Text).val(item.Value));
                });
            });    
    });
});

Now, let’s add a GetStates action method which accepts the countryId and return the states for that country in a list of SelectListItem as JSON array.

public ActionResult GetStates(int countryId)
{
    var states = new List<SelectListItem>();
    if (countryId == 1)
    {
        states.Add(new SelectListItem() {Value = "101", Text = "Michigan"});
        states.Add(new SelectListItem() { Value = "102", Text = "New York" });
    }
    else if (countryId == 2)
    {
        states.Add(new SelectListItem() { Value = "103", Text = "Kerala" });
        states.Add(new SelectListItem() { Value = "104", Text = "Goa" });

    }
    return Json(states, JsonRequestBehavior.AllowGet);
}

Here i have hard coded the Countries and States. But if you have a database which has this data, replace the hard coded values with data from your tables.

When you are editing a record, All you have to do is, load the States property in the GET action based on the CountryId which is saved.

Leave a Comment