General Web

Conditionally Populating Select Lists Client Side

When using classic ASP when I needed to populate a select list client side based on an action such as a checking a check box radio button or some other client action, I would create some client side JavaScript objects on the page and an array of these objects. When the user performed the appropriate action I would walk the array pulling the required data into the select list.

When I first started developing in ASP.net I basically continued using this pattern, battling Request Validation errors as I had changed the expected values in the drop down list. This days AJAX is a popular method of performing this kind of action, however I like to reduce repeated calls to the server if I can avoid it.

I’ve recently flipped the pattern on its head. Now I completely populate the select list server side, then on page load, client side, use jQuery to make a clone of the option, and empty the select list (or set it to another default state. Then when the user performs the appropriate action append options from the cloned list to the original list.

The following example is modified from real life form, the user selects an event an a list of marketing sources for that event is populated in the select list. The sources and events are stored in a jSON variable.

//Use a nice wide scope
var origSelSourceList;
var selSourceList;

//jSON string to hold the details
var details = [{
    "EventID": 2738,
    "Detail": "Dee Why - Wednesday, 10 August 2011 - 6:30 PM",
    "Sources": [393, 1101, 1135, 1106, 24, 1128, 1158, 1150, 863, 955, 1470, 1130, 1139, 1137, 1141]
}, {
    "EventID": 2776,
    "Detail": "Surfers Paradise - Sunday, 18 September 2011 - 11:00 AM",
    "Sources": [393, 1101, 1135, 1106, 1158, 1150, 863, 955, 1470, 1130, 1139, 1137, 1141]
}, {
    "EventID": 2782,
    "Detail": "Scarborough - Saturday, 24 September 2011 - 11:00 AM",
    "Sources": [393, 1101, 1135, 1106, 1158, 1150, 863, 955, 1470, 1130, 1139, 1137, 1141]
}];


$(document).ready(function () {
    selSourceList = $("#clientForm_Source"); //Cache the select list for later
    origSelSourceList = $("#clientForm_Source").clone(); // Make a cloned copy
    selSourceList.find('option').remove().end().append('<option value="-1">Select Event</option>');

    //Our radio buttons that cause the list
    //to be populated are in a div with an id of "forPop"
    $("#forPop input:radio").click(function () {

        //Add a first default
        selSourceList.find('option').remove().end().append('<option value="-1">Please Select</option>');

        //Event ID to find the sources for
        var id = $(this).val();

        //Find the event
        for (var i = 0; i < details.length; i++) {
            if (details[i].EventID == id) {

                //Get source for the event 
                for (var j = 0; j < details[i].Sources.length; j++) {
                    //Find and Clone the option from our cloned copy of the select list                             
                    selSourceList.append($(origSelSourceList).find('option[value="' + details[i].Sources[j] + '"]').clone());
                }
                break; // Found our event so stop looping
            }
        }
    });

});

The beauty of this technique is that it works nicely with ASP.net’s request validation, but can be used with any server side technology

Referencing External Script Libraries

Google’s CDN is a very powerful way of accessing JavaScript libraries like jQuery, Mootools etc. This is a great article on why you should be using a CDN for this accessing these kind of libraries:3 reasons why you should let Google host jQuery for you . The one problem is dealing with them when your page is accessed via https and the “mixed content” warning the browser can throw.

Fortunately there is a very simple solution:

<script type="text/javascript"  src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>

Notice the complete lack of http or https, this is not a typo, it basically retrieves the script using the protocol the page was called with! This works particularly well in template scenarios like asp.net master pages.