ASP.NET MVC–Cascading Dropdown Lists Tutorial–Part 5.2: Cascading using jQuery.ajax() ($.ajax() and jQuery Templates)
- Part 1 – Defining the problem and the context
- Part 2 – Cascading using normal FORM post (Html.BeginForm helper)
- Part 3 – Cascading using Microsoft AJAX (Ajax.BeginForm helper)
- Part 4 – Cascading using FORM Hijaxing
- Part 5 – Cascading using jQuery.ajax():
- Part 5.1 – $.ajax() and DOM Objects
- Part 5.2 – $.ajax() and jQuery Templates
- Part 5.3 – $.ajax() and Knockout.js
- Part 6 – Creating a jQuery Cascade Select Plugin
Part 5.2: Cascading using jQuery.ajax() ($.ajax() and jQuery Templates)
We will reuse the controller from Part 5.1 and add a new action called jQueryTemplates:
public virtual ViewResult jQueryTemplates( ) { return View( MVC.CascadingDropDownLists.DropDownjQueryAjaxPost.Views.jQueryTemplates ); }
And of course the jQueryTemplates.cshtml:
<fieldset> <legend>Continents</legend> <div id='continentsContainer'> </div> </fieldset> <fieldset> <legend>Countries</legend> <div id='countriesContainer'> </div> </fieldset> <fieldset> <legend>Cities</legend> <div id="citiesContainer"> </div> </fieldset>
Compared to Part 5.1 where we had some empty select tags here we have only empty div tags. We will use jQuery Templates (see the References section for jQuery Templates documentation and samples) to define templates for the following:
-
Continents and Countries dropdown lists
-
Cities table
-
“No Information available”
For the Continents and Countries dropdown lists we will define a template called selectTemplate:
<script id="selectTemplate" type="text/html"> {{if options.length}} <select id='${id}'> <option value=''>${choose}</option> {{each options}} <option value='${Id}'>${Name}</option> {{/each}} </select> {{else}} {{tmpl '#noInfoTemplate'}} {{/if}} </script>
This is how we define a template. It has a name to help identify it and a type. The template receives, as a parameter an object with 3 properties:
-
id – becomes the select tag id
-
choose – becomes the first option ([Please select a continent])
-
options – an array of objects that have an Id and Name property
The ideea si simple. If there are any options then we output a select tag and for each option and option tag. If the options array is empty we call another template called “noInfoTemplate” that will output the text “No Information Available” (or anything we want).
The citiesTemplate:
<script id="citiesTemplate" type="text/html"> {{if cities.length}} <table> <tr> <th>Name</th> <th>Population</th> </tr> {{each cities}} <tr> <td>${Name}</td> <td align='right'>${Population}</td> </tr> {{/each}} </table> {{else}} {{tmpl '#noInfoTemplate'}} {{/if}} </script>
We follow the same idea. If the cities array is empty we call the noInfoTemplate, otherwise we output a table by using the {{each}} template tag.
And finally the very complicated noInfoTemplate:
<script id="noInfoTemplate" type="text/html"> No information available </script>
This is not all. We still need to perform the ajax requests and fill the templates with data. We can copy the functions form Part 5.1 and do some adjustments:
<script type='text/javascript'> $(document).ready(function () { //Load the continents $.ajax({ url: '@Url.Action( MVC.CascadingDropDownLists.DropDownjQueryAjaxPost.GetContinents( ) )', type: 'GET', success: function (data) { $("#continentsContainer").html($("#selectTemplate").tmpl({ id: 'continents', choose: '[Please select a continent]', options: data })); $('#countriesContainer').html($('#noInfoTemplate').tmpl()); $('#citiesContainer').html($('#noInfoTemplate').tmpl()); } }); //Catch the continents change event $('#continents').live('change', function () { $('#citiesContainer').html($('#noInfoTemplate').tmpl()); if ($('#continents option:selected').val() != '') { $.ajax({ url: '@Url.Action( MVC.CascadingDropDownLists.DropDownjQueryAjaxPost.GetCountries( ) )', data: { continentId: $('#continents option:selected').val() }, type: 'GET', success: function (data) { $("#countriesContainer").html($("#selectTemplate").tmpl({ id: 'countries', choose: '[Please select a country]', options: data })); } }); } else { $('#countriesContainer').html($('#noInfoTemplate').tmpl()); } }); //Catch the countries change event $('#countries').live('change', function () { if ($('#countries option:selected').val() != '') { $.ajax({ url: '@Url.Action( MVC.CascadingDropDownLists.DropDownjQueryAjaxPost.GetCities( ) )', data: { countryId: $('#countries option:selected').val() }, type: 'GET', success: function (data) { $("#citiesContainer").html($("#citiesTemplate").tmpl({ cities: data })); } }); } else { $('#citiesContainer').html($('#noInfoTemplate').tmpl()); } }); }); </script>
See it in action
Cascading Dropdown Lists - jQuery Templates
The code is much simple and clean now. We only have 1 line of code to create all 3 tags by calling the tmpl() function with the data returned from the server. But we still have to manually call the NoInfoTemplate if no data is returned or if there is nothing selected and there is still a lot of plumbing.
In Part 5.3 we will use Knockout.js to further improve the way we perform the cascading.