Auto-populating Select Boxes using jQuery & AJAX

Update: due to popular demand, I’ve caved in, and written a plugin and demos with multiple-select boxes populating each other and driven from MySQL.

View: Auto-populate multiple select boxes

If you are familiar with using select boxes for categorisation and sub-categories, such as ebay does when selling an item, usually this can require a lot of JavaScript to maintain the select boxes, but jQuery can hugely simplify this task by adding a dash of AJAX.

The Goal

Allow the user to select a top level category from one select box and to automatically populate the sub-category.

Prerequisites

  1. Latest copy of jQuery
  2. A basic understanding of JSON (don’t let this put you off – it’s really very, very easy)
  3. A server-side script that can respond to the AJAX request (though I’ve provided a simple example)

Demo

Our demo will specifically look to build a simple form that allows us to book human resource for a project. The top level category is the resource type, and the sub-category will list the individual’s names.

See the demo in action

How it works

Once the top level category select is changed, it sends an AJAX request for the sub-categories. The result of which are converted to select options and the sub-category select’s elements are replaced.

Unobtrusive JavaScript

First things first: as with any page that is loaded with JavaScript and AJAX functionality, it should work without JavaScript.

To achieve this for our tutorial here’s what we need to ensure:

  1. When the page is loaded, the sub-category is loaded (if the top level has a selected item).
  2. There is a ‘load sub-category’ button the user can select to re-load the page. We will hide this button with a <noscript> tag in our demo.

The Code

There are 4 parts to this demo.

  1. The page’s HTML.
  2. The server-side code to produce the dynamic page (i.e. to pre-load the select boxes when the user first visits).
  3. The jQuery & JavaScript.
  4. The JSON response (which will reuse the server-side code).

HTML

<form action="/select_demo.php">
  <label for="ctlJob">Job Function:</label>
  <select name="id" id="ctlJob">
    <option value="1">Managers</option>
    <option value="2">Team Leaders</option>
    <option value="3">Developers</option>
  </select>
  <noscript>
    <input type="submit" name="action" value="Load Individuals" />
  </noscript>
  <label for="ctlPerson">Individual:</label>
  <select name="person_id" id="ctlPerson">
    <option value="1">Mark P</option>
    <option value="2">Andy Y</option>
    <option value="3">Richard B</option>
  </select>
<input type="submit" name="action" value="Book" />
</form>

Server-side

This is just a simple example, but it should be obvious that you can expand this to go off to a database and return an object in a JSON data structure:

<?php
if ($_GET['id'] == 1) {
  echo <<<HERE_DOC
    [ {"optionValue": 0, "optionDisplay": "Mark"}, {"optionValue":1, "optionDisplay": "Andy"}, {"optionValue":2, "optionDisplay": "Richard"}]
HERE_DOC;
} else if ($_GET['id'] == 2) {
  echo <<<HERE_DOC
    [{"optionValue":10, "optionDisplay": "Remy"}, {"optionValue":11, "optionDisplay": "Arif"}, {"optionValue":12, "optionDisplay": "JC"}]
HERE_DOC;
} else if ($_GET['id'] == 3) {
  echo <<<HERE_DOC
    [{"optionValue":20, "optionDisplay": "Aidan"}, {"optionValue":21, "optionDisplay":"Russell"}]
HERE_DOC;
}
?>

Note that this is not accessible. To ensure accessibility, the server side will handle the pre-population of the select boxes as the page is loaded. Here is an example (excluding the headers, footers and JavaScript) of the accessible example.

JSON Response

If I pass the server side id = 2, i.e. /select.php?id=2&ajax=true, the return value is (the ajax=true is an arbitrary flag that I’m using to differentiate between a normal user request and one done via AJAX):

[ {"optionValue":10, "optionDisplay": "Remy"},
{"optionValue":11, "optionDisplay": "Arif"},
{"optionValue":12, "optionDisplay": "JC"}]

The enclosing square brackets denotes an array and each element is separated by a comma.

Within the array are three objects. If you’re familiar with PHP or Perl, you can basically treat these as hashes. The objects have keys (in this case two keys, one called ‘optionValue’ and one called ‘optionDisplay’), and values. Note that keys don’t need to be wrapped in quotes (though in some cases you will need them sometimes).

There are two ways which we can get the data out of this structure (assuming j is the structure):

alert(j['optionDisplay'])

Or:

alert(j.optionDisplay)

jQuery & AJAX Request

Our JavaScript is going to attach itself after the page is load, and fire an event each time the job function select box is changed.

The event will send the new value of the select box and reload the contents of the person select box.

Note that I’m be a bit naughty here, in that I’m plugging HTML directly in to the DOM.

Each item in the JSON response is looped round and used to build up the new options for the select box. As the response is an array (as mentioned earlier), we can call the .length method on it.

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" charset="utf-8">
$(function(){
  $("select#ctlJob").change(function(){
    $.getJSON("/select.php",{id: $(this).val(), ajax: 'true'}, function(j){
      var options = '';
      for (var i = 0; i < j.length; i++) {
        options += '<option value="' + j[i].optionValue + '">' + j[i].optionDisplay + '</option>';
      }
      $("select#ctlPerson").html(options);
    })
  })
})
</script>

Where to take it next

So that’s the primer. Next steps: upgrade, integrate, extend and stylise. Below is an example of the category selection when submitting an item for sale on Ebay.

Ebay Category Selection

It should be a simple next step to integrate a database behind the selection methods and create more complicated selection like this Ebay example.

Let me know if you spot any glaring errors or have any comments.

176 Responses to “Auto-populating Select Boxes using jQuery & AJAX”

  1. HI All,

    I am doing a similar one in struts2 but I have very less knowledge about JSON and JQUERY .I have a 2 select boxes.In the first box I select a value and made an Ajax call in which I send the selectedValue which will take me to action class.In my action class I wrote like this…

    
    @JSON(name="jSONArray")
        public void getCityVals()
        {
            Country c=StorageBean.getCountryList().get(selectedCountry);    //this is passed from jsp via AJax call      
    
             atrHMap1=c.getCityList();
            JSONArray jSONArray=new JSONArray();
             jSONArray.addAll((Collection) atrHMap1);      
    
             for (int i = 0; i  "+jSONArray.getString(i));
             }
        }   
    
    

    and in my JSP I have…

    
    $(document).ready(function() {
                $(function() {
                    $("select#countries").change(function() {
                        $.getJSON("cityAction.action?search=",{countryId: $(this).val(), ajax: 'true'}, function(j){
                        var options = '';
                            for (var i = 0; i < j.length; i++) {
                                options += '' + j[i].name + '';
                            }
                            $("select#cities").html(options);
                        })
                    })
                })
            });
    

    I dunno how to use my JSON data and use the above one(just modified it based on example given !!! ) to populate them in my 2nd select box…
    Kindly need guidance !!!

  2. i didnt shared solution, just for i wanted to know how many will ask me, so far just one, so i will share it, moreover this isnt usual, many will get paid for this solution in their web projects, this inst linux, i fought for solution googled, trialed in error and needed in in very urgent situation and get paid very few for what i did. but i will, have to check it in my project though :) i forgot

  3. IE needs these three lines in your ie PHP project, its php code

    header(‘Cache-Control: no-cache, must-revalidate’);
    header(‘Expires: Mon, 26 Jul 1997 05:00:00 GMT’);
    //
    //
    header(‘Content-type: application/json’);

    i will be glad for each your saying thanks

  4. fantomx1 … you’re a douche. Yes, this is a professional field, yes, we deserve to be paid for our time, but this is a fracking blog man! Either accept the advice with gratitude or go away. You’re getting after the author for a mistake, trying to make a dime off your ‘knowledge’, posting something that has nothing to do with the problem as the answer, and then expecting all of our thanks? Try not to be such a douche in the future.

  5. You call this a tutorial? Its just a bunch of random information jumbled together. How any of you got this to work is beyond me. Thanks for wasting my whole day! Next time, try to have all the code to make it work and explain it so it is understandable. You just have a bunch of random BS in here, code snipets and vague descriptions. This is one of the WORST tutorials Ive ever seen in MY LIFE. F*CK YOU

  6. Remy,

    You rock, your code rocks.

    That is all.

    Lots of love,
    Eamo!

  7. Fuahole… if you actually want help for free, then throwing disrespect and insults at an author who has generously blogged his experience and expertise for no personal gain, is not the way to go about it. If you’re frustrated at your own inabilities, trying asking nicely for help. You never know, someone might be nice back and send you to a suitable beginners’ forum. Shouting obscenities is only going to be met with silence or derision. Or laughter at your expense. Think about it, learn some manners and grow up.

  8. Fuahole, we all managed fine with it. Must just be you.

    You spent a “whole day” on this? Really?

    You should hire someone.

  9. Hey Fuahole!

    A lot of work goes into creating a site like this so that you can read it for free at a time of your leisure.

    If you are frustrated with your skills it is completely unfair to swear and abuse the author. Take a class, ask for help or do something else. Don’t abuse generous people who give their time for free so others can learn from their knowledge.

  10. Fuahole,

    You deserve that name, cuz its sounds “asshole” and that you deserve to be called of that as well.

    The tutorial is a bit easy and for sure to all web dev guys out there. You probably not a web dev guy, maybe you’re just pretending that you’re clever but truth is NOT. you are weak!!!

  11. Some alternative:
    instead of building the options-text in javascript from the previously constructed json-array, let the server-php-part build the html-fragment and populate the select-tag like this:

    $("select#ctlJob").change(function(){
        $("select#ctlPerson").load("/select.php",{id: $(this).val(), ajax: 'true'});
    });
    

    First building that JSON-Array and later iterating it to then build a html-fragment seems avoidable to me.

  12. For anyone wondering why this won’t work “as is” under jquery 1.4, it’s because the way in which JSON is parsed by jquery changed at 1.4 to use the browsers native JSON parser.

    The effect of this is that you now need to wrap all properties and values in double quotes (ie valid JSON) for the response to be parsed.

    ie this will work:

    [ {"optionValue": "0", "optionDisplay": "Mark"}, {"optionValue":"1", "optionDisplay": "Andy"}, {"optionValue":"2", "optionDisplay": "Richard"}]

    this will not:

    [ {optionValue: 0, optionDisplay: 'Mark'}, {optionValue:1, optionDisplay: 'Andy'}, {optionValue:2, optionDisplay: 'Richard'}]

  13. I just wish you had created a demo like the eBay category selection.
    I’m needing one for a GoogleBase module for an e-commerce store where I can select the Primary Product Type. GoogeBase’s product type taxonomy goes probably 8 levels and has 3700+ entries.

    I’m attempting to use the mcDropdown jQuery plugin but it is still difficult to do.

  14. I have modified the code to enable it to send the values for the previous selects. All of them instead of just the select before. I have 6 selects all dependent and to get the values, I need all the values of all the previous selections. If you are interested I could send it to you. It adds a tree param to options.

  15. Jon–I’d be interested in that code, thanks! (bigbenchrob google mail)

  16. For me it’s not auto populating – I’m probably being stupid.
    Also Next to each select box there’s a button – I tried to delete the value to get rid of it but there’s no luck.

    Please could you take a few minutes to help me.
    Thank you

  17. On jquery doc : As of jQuery 1.4, if the JSON file contains a syntax error, the request will usually fail silently. Avoid frequent hand-editing of JSON data for this reason. JSON is a data-interchange format with syntax rules that are stricter than those of JavaScript’s object literal notation. For example, all strings represented in JSON, whether they are properties or values, must be enclosed in double-quotes.

    Please used “..”

    echo '[ {"optionValue": "0", "optionDisplay": "Mark"}, {"optionValue":"1", "optionDisplay": "Andy"}, {"optionValue":"2", "optionDisplay": "Richard"}]';

  18. Hi remy, nice job

    but i have a question, i want to make te same, but that I want to do is re-populate is a html table when change the , actually i don’t have any idea of how can i do it, can you please give me a hand.

  19. Just a couple of notes for style points ;-):
    1. For the PHP side of things json_encode() is a nice way to turn readable code (ie Arrays) into json data.
    2. in the javascript $.each() provides a much cleaner way to iterate over the results. As a totally niaive example of the syntax:

    $.each(response.results,
    function(key,value) {
    options += '

    ';
    })

  20. If anyone could help me apply this exact code into WordPress, to display a list of top level categories, and then accept a selection (in the second drop down) of a child category, I would be very, very grateful.

    Please leave a comment here if you can help. I don’t have the expertise to change out the JSON return to being a WordPress query on the categories.

    Luke

  21. A missing part to the chaining is resetting downstream selectors when there are more than 2 selectors. Because, if selects #1 #2 and #3 are set and then #1 is altered, #2 updates but #3 (and below) don’t. When #1 changes #2′s code via AJAX the #2 change event doesn’t fire, so whilst #2′s code is reset via AJAX, #3 and so on remain as last set – which is not normally your intent.

    The change needed is small. In the change function for each select at a trigger to fire the change for the next in line. The call is needed is .trigger(“change”);. Consider selects #ctlJob, #ctlPerson and #ctlDesk – chained in that order. We add the following to the end of the code for change function of #ctlJob:
    $("select#ctlPerson").trigger("change");

    Now, when #1 resets #2 it also fires #2′s change making it repopulate #3 in turn. If using a #4 select, then #2′s change function would add code to trigger #3′s change event and so on down.

    There are probably faster ways – I’m not a JS expect – but this does at least work and is an aspect omitted from all the chained select demos I have seen.

  22. everybody if you can’t get it to work thats because this code isn’t compatible with latest jquery. Head on to http://stackoverflow.com/questions/5155467/auto-populating-select-boxes-using-jquery-and-ajax-not-working-in-anything-newe & you will find your solution there.

    credits to the OP over there :)

  23. Tom Davies, lean your head forward so I can kiss it.

  24. This is exactly what I want for a project of mine, except I know nothing of php, I use asp…. I haven’t seen a good example like this in asp though :(
    Would it be possible for someone to show the same example but php code changed to asp??
    I know that is asking a bit much, but if I don’t ask… :)

  25. Thanks i am newbie to JQuery and also to web designing profession thanks a lot
    This tutorial helped me a lot .

  26. Hi Tom Davies,

    I had used this code in past around 1-2 years back and it worked. But today when I tried to use it again then it won’t work. I spent hours but it simply won’t work. Then I started reading comments and your solution has worked.

    From Tom Davies:


    For anyone wondering why this won’t work “as is” under jquery 1.4, it’s because the way in which JSON is parsed by jquery changed at 1.4 to use the browsers native JSON parser.

    The effect of this is that you now need to wrap all properties and values in double quotes (ie valid JSON) for the response to be parsed.

    ie this will work:

    [ {"optionValue": "0", "optionDisplay": "Mark"}, {"optionValue":"1", "optionDisplay": "Andy"}, {"optionValue":"2", "optionDisplay": "Richard"}]

    this will not:

    [ {optionValue: 0, optionDisplay: 'Mark'}, {optionValue:1, optionDisplay: 'Andy'}, {optionValue:2, optionDisplay: 'Richard'}]

    Note to author: You’re suggesting to use latest version of jquery then please update your code also so that it works with latest version of jquery as suggested by Tom.

    Thanks once again! :)