How to create cascading drop-down list
Solution 1:
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.