MVC DropDownListFor fill on selection change of another dropdown

bind child dropdown on change of parent dropdown item? bind dropdown on selection change? bind dropdown by using jquery? how to return json from action method in controller? how to format child dropdown items cascading dropdownlist in gridview edit mode cascading dropdownlist in mvc cascading dropdownlist jquery mvc cascading dropdownlist

Binding DropDownListFor from enum, database and some hard coded values in our previous article MVC dropdown binding best ways. In this article we will try to bind child Dropdown on selection change of parent Dropdown, say Country to State or Sate to City, by using jQuery which will call an action in controller and return JSON for selected id, and with the help of jQuery append values to child Dropdown. We will try to create page to add new employee and state and city will be used as parent and child Dropdown.

alt text

Let's see the tables we are going to use:

public partial class State
{
    public int StateId { get; set; }
    public string StateName { get; set; }
    public string Abbr { get; set; }
} 
public partial class City
{
    public int CityId { get; set; }
    public string CityName { get; set; }
    public int StateId { get; set; }
}

Employee Model:

public class Employees
{
    [Key]
    public int EmployeeId { get; set; }

    [Required, Display(Name="Employee Name")]
    public string EmployeeName { get; set; }

    [Required, Display(Name = "Address")]
    public String Address { get; set; }

    [Required, Display(Name = "State")]
    public int State { get; set; }

    [Required, Display(Name = "City")]
    public int City { get; set; }

    [Display(Name = "Zip Code")]
    public String ZipCode { get; set; }

    [Required, Display(Name = "Phone #")]
    public String Phone { get; set; }
}

As you can see, I have not added anything in our model for list of states or cities because we are using Code first, which will create the database tables, we will try to get data from database and pass to view by using ViewBag, here is our HttpGet and HttpPost action method:

[HttpGet]
public ActionResult Create()
{
    ViewBag.StateList = db.States;
    var model = new Employees();
    return View(model);
}
[HttpPost]
public ActionResult Create(Employees model)
{
    if (ModelState.IsValid)
    {
        // code to save record  and redirect to listing page
    }
    ViewBag.StateList = db.States;
    return View(model);
}

HTML code for both state and city dropdown:

<div class="form-group">
    @Html.LabelFor(m => m.State,  new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownListFor(m => m.State,
              new SelectList(ViewBag.StateList, "StateId", "StateName"),
              "Select state",
              new { @class = "form-control", @onchange="FillCity()" })
        @Html.ValidationMessageFor(m => m.State, "", new { @class = "text-danger" })
    </div>
</div>

<div class="form-group">
    @Html.LabelFor(m => m.City, new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownListFor(m => m.City,
       new SelectList(Enumerable.Empty<SelectListItem>(), "CityId", "CityName"),
              "Select city",
              new { @class = "form-control" })
        @Html.ValidationMessageFor(m => m.City, "", new { @class = "text-danger" })
    </div>
</div>

As you can notice we used @onchange="FillCity()" in our State dropdown so we need a JavaScript function which will be call on change of state. If you are from asp.net background then forgot about the postback, in mvc there is no postback concept so we don't need viewstate of controls so the pages are light weight. Here is our FillCity function:

@section Scripts {
<script>
  function FillCity() {
    var stateId = $('#State').val();
    $.ajax({
        url: '/Employees/FillCity',
        type: "GET",
        dataType: "JSON",
        data: { State: stateId},
        success: function (cities) {                    
            $("#City").html(""); // clear before appending new list 
            $.each(cities, function (i, city) {
                $("#City").append(
                    $('<option></option>').val(city.CityId).html(city.CityName));
            });
        }
    });
  }
</script>
}

Here we used $.each to loop the items and add item by item to city dropdown. We used to call FillCity action method in our Employees controller.We need a separate action method which can return cities on the basis of selection change and return JSON string.

public ActionResult FillCity(int state)
{
    var cities = db.Cities.Where(c => c.StateId == state);
    return Json(cities, JsonRequestBehavior.AllowGet);
}

See how we can return json from any action method in our controller. If you want to see the complete html of the page then it is here.

@model MyApp.Models.Employees
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
@using (Html.BeginForm()) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>New Employee</h4>      
    <div class="form-group">
        @Html.LabelFor(m => m.EmployeeName, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.EmployeeName, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.EmployeeName, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Address, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Address, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Address, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.State,  new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(m => m.State,
                  new SelectList(ViewBag.StateList, "StateId", "StateName"),
                  "Select state",
                  new { @class = "form-control", @onchange="FillCity()" })
            @Html.ValidationMessageFor(m => m.State, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.City, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(m => m.City,
           new SelectList(Enumerable.Empty<SelectListItem>(), "CityId", "CityName"),
                  "Select city",
                  new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.City, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ZipCode, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.ZipCode,  new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.ZipCode, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Phone, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Phone, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Phone, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-success" />
            <a href="/Employees" class="btn btn-warning" >Cancel</a>
        </div>
    </div>
</div>
}

If you want to add more column value into dropdown text you can concatenate them easily, say we want to show both Id and text in city drop down then we simmply show it like this:

$('<option></option>').
   val(city.CityId).html(city.CityId + " - " + city.CityName)); 

Whatever we see here is not complete to maintain the selected value if we found the model invalid in our post method and return back to the view then current selected state's cities will be lost same will happen when we need to fill and select the value in city dropdown for a saved records. We need to add one more JavaScript method to check on document.ready if there is any value already selected in state dropdown then call the FillCity method and fill our city dropdown and selected the city value which we get from the model.

I am leaving it for you so you can do a little bit practice, hope you will easily complete it, best of luck.

<< MVC DropDownListFor fill on selection change of another dropdown

MVC EnumDropdownListFor bind with enum example >>

Ali Adravi Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
  • mvc
  • dropdownlistfor
  • jquery
  • javascript
By Ali Adravi On 11 Apr, 15  Viewed: 168,729

Other blogs you may like

mvc search page example with code

MVC Searh page with pagination: It’s very easy to create a search page in asp.net but when I try to create the same in MVC I faced many problems, how to create model, how to keep searched values in search controls, pagination, I found myself nowhere, so start searching for some good examples but... By Ali Adravi   On 25 Aug 2013  Viewed: 40,117

MVC insert update delete and select records

CRUD (Create, Retrieve, Update and Delete) in MVC. When we start to learn new language, first we try to run an application with “Hello World” and then CRUD functionality. So in this article we will see how to select records from database (with WebGrid, pagination and sort functionality), update a... By Ali Adravi   On 17 Aug 2013  Viewed: 105,948

How to create a single thanks page for entire controller in MVC

Sometimes we need a thanks page say we have user registration, change password, activate account functionality in our application then we need a thanks page after registering with our site, to say thanks for registering with us or showing confirmation that your password is successfully changed or... By Hamden   On 30 Jun 2013  Viewed: 3,738

MVC jquery autocomplete with value and text field

In MVC, autocomplete with jquery is the best way to pull data from database and render according to our requirements, so in this article we will use jquery to show the auto complete text box without any ajax controls. We need a method to get the data from database, a controller method to handle the... By Ali Adravi   On 29 Jun 2013  Viewed: 6,997

Upload files with model data in MVC

Upload multiple files with model data in MVC is really very easy, when I started to test by uploading some files, I though it would be more complicated but it is really not. In my previous post [ASP.Net MVC file upload][1], I promised to post soon about how to upload multiple files. When I was... By Ali Adravi   On 04 Jun 2013  Viewed: 25,493