Cascading drop down lists are very common nowadays. Today I have written a simple sample about how they can be implemented using ASP.NET MVC and JQuery.
When the sample is executed, the user is presented with a first drop down list that will contain a list of countries. Once the user selects one of the countries, a request to the server is made via AJAX and the results will be loaded and presented in a second drop down list showing a list of cities belonging to the selected country. To keep this sample as simple, we are not going to use databases. Instead, we are going to use some auxiliary methods to generate some dummy data.
In the controller, we will have a collection initializer to generate a list of countries.
private IEnumerable<string> GetCountries
{
get
{
return new List<string> { “US”, “Canada”, “UK” };
}
}
We will also need another collection initializer for the cities.
private IEnumerable<string> GetStates(string country)
{
var list = new List<string>();
switch (country)
{
case “US”:
list.AddRange(new string[]
{
“New York”,
“Florida”,
“California”,
“Wisconsin”
});
break;
case “Canada”:
list.AddRange(new string[]
{
“Ontario”,
“Quebec”,
“Nova Scotia”,
“New Brunswick”,
“British Columbia”,
“Alberta”
});
break;
case “UK”:
list.AddRange(new string[]
{
“Scotland”,
“London”,
“Northern Ireland”,
“Wales”
});
break;
default:
break;
}
return list;
}
With our auxiliary methods in place, we can now write two actions. One will receive a country and will return the list of cities belonging to the selected country via ajax.
public JsonResult GetStatesAjax(string country)
{
var states = GetStates(country);
return Json(states, JsonRequestBehavior.AllowGet);
}
The other will be our index function and will set a ViewBag variable with the list of countries
public ActionResult Index()
{
var countries = new SelectList(GetCountries);
ViewBag.Countries = countries;
return View();
}
With all our methods in place, now we can implement our view.
We can define the first drop down list that will contain the countries this way:
<div class=”form-group”>
<label class=”control-label”>Select country</label>
@Html.DropDownList(“Country”, ViewBag.Countries as SelectList, “– Select One –“, new { @class = “form-control” })
</div>
And the second drop down list that will contain the cities. This one will be hidden and will be shown once the user selects one of the countries and the server returns the information.
<div class=”form-group” id=”ddStates”>
<label class=”control-label”>Select state</label>
<select id=”States” class=”form-control”></select>
</div>
With the controls in place, we can now define our client logic for this sample to work.
$(function () {
var $ddStates = $(“#ddStates”);
var $states = $(“#States”)
$ddStates.hide(); //Initially hide the cities drop down list
$(“#Country”).change(function () {
var $element = $(this);
var value = $element.val();
//send the request to the server using the selected country
$.getJSON(‘@Url.Action(“GetStatesAjax”)’, { country: value })
.done(function (data) {
$states.html(“”); //Clear the cities drop down list
//Show the drop down list only if there is 1 or more cities in the response
(data.length > 0 && $ddStates.show()) || $ddStates.hide();
//Populate the cities drop down list
$.each(data, function (index, value) {
var opt = $(“<option>”).text(value).appendTo($states);
})
})
.fail(function (jqxhr, textStatus, error) {
var err = textStatus + “, ” + error;
console.log(“Invalid Request: ” + err);
});
});
});
There is nothing wrong with the presented sample, but, we can improve the performance quite a bit by using the html property of the jQuery object instead of appending directly to the drop down list.
var html = ”;
$.each(data, function (index, value) {
html += ‘<option>’ + value + ‘</option>’;
});
$states.html(html);
We can even make it faster by using the Join method from the JavaScript arrays.
var html = ‘<option>’ + data.join(‘</option><option>’) + ‘</option>’;
$states.html(html);
Here at Palm Beach Software Design we take the time to determine the best implementation based on your business needs, we strive to create custom software for our customers that will increase profits and productivity.