This guide will walk you through building cascading drop down using knockoutjs and ASP.NET MVC. We leverage knockoutjs to create UI which update itself based on user interaction. Sample can be downloaded from here.
Below view is presented with drop down list loaded with countries and upon selecting any country user is presented with another drop down which lists states for the selected country. This sample uses jQuery.getJSON to fetch list of states for selected country. Server will return state list in JSON format.
Magic of knockoutjs
We have created a ASP.NET MVC view and model with MVVM pattern used by knockoutjs. Whenever the data source refresh at that time we only need to update underlying viewModel and the rest will be taken care by knockoutjs including updating UI based on refreshed data.
Code snippet for Home controller & State model class:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Country = new SelectList(Country.GetCountryList(), "Code", "Name");
return View();
}
public ActionResult GetStates(string id = "")
{
var stateList = State.GetStates()
.Where(s => s.CountryCode.ToLower() == id.ToLower());
return this.Json(stateList, JsonRequestBehavior.AllowGet);
}
}
// State model class
// Property of State class is used to
// bind view with knockoutjs viewmodel
public class State
{
public string CountryCode { get; set; }
public int StateId { get; set; }
public string StateName { get; set; }
}
Code snippet for index.cshtml:
<p>
<b>Select Country :</b> @Html.DropDownList("ddlCountry", ViewBag.Country as SelectList, "Select...", new { onchange = "FetchStates();" })
</p>
<p data-bind="visible: states().length > 0">
<b>Select State :</b> <select data-bind="options: states, optionsText: 'StateName', optionsValue: 'StateId', optionsCaption: 'Choose...'"></select>
</p>
Code snippet for ViewModel defined in JavaScript:
function CascadingDDLViewModel() {
this.states = ko.observableArray([]);
}
var objVM = new CascadingDDLViewModel();
ko.applyBindings(objVM);
We are creating a view model with states property of type ko.observableArray. Observable type in knockoutjs will notify automatically whenever underlying object is updated.
In index.cshtml snippet, we are using this states property with data-bind attribute that binds DOM element behavior with knockoutjs ViewModel. So DOM elements will be updated automatically whenever ViewModel changes.
Following JavaScript function will be called whenever user selects a country. With the help of jQuery.getJSON method, we fetch list of states and assigning the states to the states property of the viewmodel. As the viewmodel changes. knockoutjs will take care of loading a dropdown for states.
function FetchStates() {
var countryCode = $("#ddlCountry").val();
$.getJSON("/Home/GetStates/" + countryCode, null, function (data) {
objVM.states(data);
});
}
Sample code can be downloaded here.