Creating Cascading DropDownLists using ASP.NET MVC 4 and jQuery
Sometimes you need to display DropDownLists in your ASP.NET MVC views such
that values in one DropDownList are dependent on the value selected in another
DropDownList. The most common example of such a functionality is countries and
states DropDownLists where based on a selected country you need to populate the
states DropDownList. This article shows how such a cascading DropDownLists can
be developed using ASP.NET MVC and jQuery.
Have a look at the following figure that shows two DropDownLists:
As you can see the country DropDownList contains a list of countries along
with the first entry of "Please select". Upon selecting a country the states
DropDownList displays the states belonging to the selected country. When the
page is loaded the country DropDownList has "Please select" entry selected and
states DropDownList is disabled. Upon selecting a country the states
DropDownList is enabled so that state selection can be made. Clicking on the
Submit button submits the form to an action method for further processing.
Begin by creating a new ASP.NET MVC4 project based on empty project template.
Add Scripts folder to the project and place jQuery library into it. Then add
HomeController to the Controllers folder. In a real world scenario you will get
countries and states from a database. Here, for the sake of simplicity, we will
use some hardcoded country and state values.
Now add the following action method to the HomeController:
public ActionResult Index()
{
List<string> items = new List<string>();
items.Add("Please select");
items.Add("USA");
items.Add("UK");
items.Add("India");
SelectList countries = new SelectList(items);
ViewData["countries"] = countries;
return View();
}
The above code shows Index() action method. Inside the Index() method a
generic List of strings is created to hold country names and a few countries are
added to it. The DropDownList HTML helper of ASP.NET MVC requires its data in
the form of SelectList object. Hence a SelectList is created based on the
countries List. The SelectList object is passed to the view using countries
ViewData variable.
Next, add another action method to the HomeController as shown below:
public JsonResult GetStates(string country)
{
List<string> states = new List<string>();
switch (country)
{
case "USA":
states.Add("California");
states.Add("Florida");
states.Add("Ohio");
break;
case "UK":
//add UK states here
break;
case "India":
//add India states hete
break;
}
return Json(states);
}
As you can see the GetStates() action method accepts a string parameter named
country and returns JsonResult. The GetStates() returns JsonResult because this
method will be called using jQuery and states information is to be returned as
JSON data. The GetStates() method contains a simple switch statement that adds a
few states to states List based on the country value. Finally, the states
generic List is returned to the caller using Json() method. The Json() method
converts any .NET object into its JSON equivalent.
Now, add Index view to the Views folder and key-in the following markup to
it:
<% using(Html.BeginForm("ProcessForm","Home",FormMethod.Post)){ %>
<div>Select Country :</div>
<%= Html.DropDownList("country", ViewData["countries"] as SelectList)%>
<br /><br />
<div>Select States :</div>
<select id="state"></select>
<br /><br />
<input type="submit" value="Submit" />
<%} %>
The Index view consists of a <form> that houses two DropDownLists. The
country DropDownList is rendered using DropDownList HTML helper. The first
parameter of the DropDownList() helper is the name of the DropDownList and the
second parameter is the SelectList object containing DropDownList values. The
second DropDownList is added as raw <select> element whose ID is state. Although
the <form> is submitted to ProcessForm action this method is not described below
as it's not directly related to the functioning of the DropDownLists.
Now, add a <script> reference to jQuery library and also add a <script> block
in the head section of the view. Then write the following jQuery code in the
<script> block:
$(document).ready(function () {
$("#state").prop("disabled", true);
$("#country").change(function () {
if ($("#country").val() != "Please select") {
var options = {};
options.url = "/home/getstates";
options.type = "POST";
options.data = JSON.stringify({ country: $("#country").val() });
options.dataType = "json";
options.contentType = "application/json";
options.success = function (states) {
$("#state").empty();
for (var i = 0; i < states.length; i++) {
$("#state").append("<option>" + states[i] + "</option>");
}
$("#state").prop("disabled", false);
};
options.error = function () { alert("Error retrieving states!"); };
$.ajax(options);
}
else {
$("#state").empty();
$("#state").prop("disabled", true);
}
});
});
The above code shows the ready() handler. Inside the ready() handler, you
first disable the state DropDownList using prop() method. The prop() method sets
the disabled DOM property to true and thus disables the state DropDownList. Then
the change() method is used to wire change event handler of the country
DropDownList. The change event handler will be called whenever selection in the
country DropDownList changes. The change handler function first checks value
selected in the country DropDownList. If it is other than "Please select", the
code creates an options object. The options object holds various settings for
the Ajax request to made to the server for retrieving the state values. The url
property points to the GetStates() action method. The type property is set to
POST indicating that a POST method will be used while making Ajax request. The
data property contains JSON representation of the country selected in the
country DropDownList. Note that the name of this property has to match with the
name of the GetStates() method parameter. The dataType and contentType are set
to json and application/json respectively. These properties indicate the data
type of the response and request respectively.
The success handler function is called when the Ajax call to GetStates() is
successful. The success handler function receives the states returned from the
GetStates() method as an array of JSON objects. Inside the success handler you
iterate through the states array and add <option> elements to the state
DropDownList using append() method. Before appending the newly fetched states
the state DropDownList is emptied. Once t he states are populated the disabled
property of the states DropDownList is set to true using prop() method.
The error handler function simply displays an error message in an alert
dialog.
Finally, an Ajax call is made using $.ajax() method of jQuery and the options
object is passed as its parameter.
That's it! Run the application and test whether states are populated as
expected.