Cascading DropDownList in ASP.NET MVC
In this blog post you will learn how
to create cascading DropDownList in ASP.NET MVC. I will take you through step
by step approach so, let’s begin.
Case Study: I am going to create two DDLs (State and District). First DDL will let you pick state and when you pick state, it will make a parameterized JSON call using jQuery that will return matching set of districts that will be populated to second DDL. I will also show how to use proper validations with each control. Here is the animated screen that we are going to create.
Case Study: I am going to create two DDLs (State and District). First DDL will let you pick state and when you pick state, it will make a parameterized JSON call using jQuery that will return matching set of districts that will be populated to second DDL. I will also show how to use proper validations with each control. Here is the animated screen that we are going to create.
Now, let’s follow the steps.
Step 1
At very first, we need a model class
that defines properties for storing data.
public class ApplicationForm
{
public string Name { get; set; }
public string State { get; set; }
public string District { get; set; }
}
Step 2
Now, we need an initial controller that
will return an Index view by packing list of states in ViewBag.StateName.
public ActionResult Index()
{
List<SelectListItem> state = new List<SelectListItem>();
state.Add(new SelectListItem { Text
= "Bihar", Value = "Bihar" });
state.Add(new SelectListItem { Text
= "Jharkhand", Value = "Jharkhand" });
ViewBag.StateName = new SelectList(state, "Value", "Text");
return View();
}
In above controller we have a List<SelectListItem> containing states attached to ViewBag.StateName. We could get list
of states form database using Linq query or something and pack it to
ViewBag.StateName, well let’s go with in-memory data.
Step 3
Once we have controller we can add
its view and start creating a Razor form.
@Html.ValidationSummary("Please
correct the errors and try again.")
@using (Html.BeginForm())
{
<fieldset>
<legend>DropDownList</legend>
@Html.Label("Name")
@Html.TextBox("Name")
@Html.ValidationMessage("Name", "*")
@Html.Label("State")
@Html.DropDownList("State", ViewBag.StateName as SelectList, "Select a State", new { id = "State" })
@Html.ValidationMessage("State", "*")
@Html.Label("District")
<select id="District" name="District"></select>
@Html.ValidationMessage("District", "*")
<p>
<input type="submit" value="Create" id="SubmitId" />
</p>
</fieldset>
}
You can see I have added proper
labels and validation fields with each input controls (two DropDownList and one
TextBox) and also a validation summery at the top. Notice, I have
used <select id=”District”….> which is HTML instead of Razor helper this
is because when we make JSON call using jQuery will return HTML markup of
pre-populated option tag. Now, let’s add jQuery code in the above view page.
Step 4
Here is the jQuery code making JSON
call to DDL named controller’s DistrictList method with a parameter (which is
selected state name). DistrictList method will returns JSON data. With the
returned JSON data we are building <option> tag HTML markup and attaching
this HTML markup to ‘District’ which is DOM control.
@Scripts.Render("~/bundles/jquery")
<script type="text/jscript">
$(function () {
$('#State').change(function () {
$.getJSON('/DDL/DistrictList/' + $('#State').val(), function (data) {
var items = '<option>Select
a District</option>';
$.each(data, function (i, district) {
items += "<option value='" + district.Value + "'>" + district.Text + "</option>";
});
$('#District').html(items);
});
});
});
</script>
Please make sure you are using
jQuery library references before the <script> tag.
Step 5
In above jQuery code we are making a
JSON call to DDL named controller’s DistrictList method with a parameter. Here
is the DistrictList method code which will return JSON data.
public JsonResult DistrictList(string Id)
{
var district = from s in District.GetDistrict()
where s.StateName == Id
select s;
return Json(new SelectList(district.ToArray(), "StateName", "DistrictName"), JsonRequestBehavior.AllowGet);
}
Please note, DistrictList method
will accept an ‘Id’ (it should be 'Id' always) parameter of string type sent by the jQuery JSON call. Inside
the method, I am using ‘Id’ parameter in linq query to get list of matching
districts and conceptually, in the list of district data there should be a
state field. Also note, in the linq query I am making a method call
District.GetDistrict().
Step 6
In above District.GetDistrict()
method call, District is a model which has a GetDistrict() method. And I am
using GetDistrict() method in linq query, so this method should be of type
IQueryable. Here is the model code.
public class District
{
public string StateName { get; set; }
public string DistrictName { get; set; }
public static IQueryable<District> GetDistrict()
{
return new List<District>
{
new District { StateName = "Bihar", DistrictName = "Motihari" },
new District { StateName = "Bihar", DistrictName = "Muzaffarpur" },
new District { StateName = "Bihar", DistrictName = "Patna" },
new District { StateName = "Jharkhand", DistrictName = "Bokaro" },
new District { StateName = "Jharkhand", DistrictName = "Ranchi" },
}.AsQueryable();
}
}
Step 7
You can run the application here
because cascading dropdownlist is ready now. I am going to do some validation
works when user clicks the submit button. So, I will add another action result
of POST version.
[HttpPost]
public ActionResult Index(ApplicationForm formdata)
{
if (formdata.Name == null)
{
ModelState.AddModelError("Name", "Name is required field.");
}
if (formdata.State == null)
{
ModelState.AddModelError("State", "State is required field.");
}
if (formdata.District == null)
{
ModelState.AddModelError("District", "District is required field.");
}
if (!ModelState.IsValid)
{
//Populate
the list again
List<SelectListItem> state = new List<SelectListItem>();
state.Add(new SelectListItem { Text
= "Bihar", Value = "Bihar" });
state.Add(new SelectListItem { Text
= "Jharkhand", Value = "Jharkhand" });
ViewBag.StateName = new SelectList(state, "Value", "Text");
return View("Index");
}
//TODO:
Database Insertion
return RedirectToAction("Index", "Home");
}
And, this action result will accept
ApplicationForm model data and based on posted data will do validations. If a
validation error occurs, the action method calls the AddModelError method to
add the error to the associated ModelState object. The AddModelError method
accepts the name of the associated property and the error message to display.
After the action method executes the validation rules, it uses the IsValid
property of the ModelStateDictionary collection to determine whether the
resulting data complies with the model.
So, this is all. If you wish to see
the complete codes, use the links given below.
Hope this helps.
Trust me , i used to read your each and every article, in fact...i had gone through your entire website after i found it first time..
ReplyDelete:)
Great work and keep doing it.
Thank you Sukesh, all my goodness.
DeleteHi, it's very nice example. well, Do you have any idea why does the Dropdown Change Envent not fire at all? it never goes to the following section
Delete@section scripts
{
*/// here is the script***
}
Hi abhimanyu, the problem is that while changing states from drawdown list it doesn't go to script section at all. do you have any idea?
DeleteThis code is working fine.......
Delete$.getJSON('/DDL/DistrictList/' + $('#State').val(), function (data) {
in above code,i want to pass more than one parameter then how can i do this?
Dear Anonymous
Deletethis is problem related to Jquery files not getting included .I was facing the same problem so i doubt Jquery files not getting included in @Scripts.Render("~/bundles/jquery") . then i simply created new MVC 4 project with Internet option instead of empty . and its get solved .
thnks for it
ReplyDelete100% positiv for a great job. I was looking for some like this for a long time. Work perfect for me :) THX once again
ReplyDeleteThere is no ViewData item of type 'IEnumerable' that has the key 'State'.
ReplyDeletethis is the error i got when i try the example
this line
@Html.DropDownList("State", ViewBag.StateName as SelectList, "Select a State", new { id = "State" })
thanks in advance
In Controller Assign the Values to the View Bag Like This
DeleteViewBag.StateName = new SelectList(state, "Value", "Text");
Thank You for your article. I have MS SQL (2010) db, each state table (statePcode -PK; stateName) and district table (districtPcode-PK; districtName; statePcode=FK).
ReplyDeleteI want when I select state it should show the relevant district under that state, using Pcode relationship in SQL database.
Kindly help any one, I using ASP.Net MVC4 using LinQ.
Thank You
Regards
Elil
Gr8 work sir keep it up......
ReplyDeleteif i want to bind data from database then what can i do, actually i want to call city on the click of state and i make the proper procedure and table for it but i dont know how i call this plz help me i am new on mvc...
ReplyDeletei work on single dropdown but i have problem when i call the second dropdown on click of first.....
i am new on mvc, i can call the single dropdown but i have problem when i m calling the second dropdown on the click of first dropdown and speclly when i bind the dropdown from database...
ReplyDeleteplz help me....
nice its helpful
ReplyDeleteHi abhimanyu,
ReplyDeleteit's very nice example. i am trying to implement it but the problem is that while changing states from drawdown list it doesn't go to script section at all. do you have any idea?
Do you have any idea why does the Dropdown Change Envent not fire at all?
please reply asap . thanks in advance
Can we done this work without use of java script.
ReplyDeletehow to bind dropdown without using json ? there is any anoother way ?
ReplyDelete