Watch
Watch Populate Select Boxes screencast (Alternative flash version)
QuickTime version is approximately 60Mb, flash version is streaming.
View the demo used in the screencast
Preparation
There’s a fairly common case to have one select box driving the content of another. Or in fact, something driving the contents of a select box. Perhaps you’ve got categories like “easy”, “medium” and “hard”, like the categories used on this site. When someone selects “easy”, a select box populates with all the jQuery for Designers articles that are marked as easy.
Sometimes that second select box has it’s contents hidden in the page already, and sometimes you’ll want it to be called dynamically.
Think of it like this: if JavaScript is disabled, how do you want the visitor to use your page?
Let’s say for arguments sake, if JavaScript is disabled, the user sees a select box with the categories with a next button:

When the visitor hits next, it reloads to show them the article list to read:

Remember this is a contrived example for this tutorial. In practise, for SEO, I wouldn’t use a form to expose a list of my articles, equally there’s no way of going back to the state with the “next” button, etc. So please, if you’re starting out, don’t use this as a way to native your site.
What I really want to show you is how to progressively enhance this page using jQuery to dynamically populate these lists. However, what the screencast will also show you is how easy it is to include this kind of functionality for a prototype demo.
Tasks
Since we’re progressively enhancing the page, I want to remove the form’s default functionality, and replace it with my own. So the tasks are:
- When the category is changed make an Ajax request
- Take that Ajax response and insert it in to the articles select box
- If the articles select box doesn’t exist, we need to create it for the first time
- Update the form buttons, so that “next” doesn’t submit, and a “read” button appears when the article select is populated
Ajax Responders
Keeping it simple (and very much contrived), I’ve created three files that contain the articles that we want to display in the select box. Each called “select-boxes-easy.html“, “select-boxes-medium.html” and “select-boxes-hard.html” - as you can see the category name is in the filename. Here’s what easy looks like:
<option value="http://jqueryfordesigners.com/jquery-infinite-carousel/">jQuery Infinite Carousel</option>
<option value="http://jqueryfordesigners.com/bbc-radio-1-zoom-tabs/">BBC Radio 1 Zoom Tabs</option>
<option value="http://jqueryfordesigners.com/coda-slider-effect/">Coda Slider Effect</option>
<option value="http://jqueryfordesigners.com/image-cross-fade-transition/">Image Cross Fade Transition</option>
Essentially it’s the contents of the select element. Simple, eh?
Starting HTML
Our form starts with an initial select box and a “next” button:
<form action="select-boxes.html">
<label for="category">Category:</label>
<select name="category" id="category">
<option value="easy">Easy</option>
<option selected value="medium">Medium</option>
<option value="hard">Hard</option>
</select>
<input type="submit" id="next" value="next »" />
</form>
Progressively enhancing with jQuery
Note that the screencast doesn’t run in the same order. In fact, it will show you how to populate quickly first. For the written tutorial, I want to take you through each step to getting this effect working.
In this example, I put jQuery right before the </body> tag and directly below jQuery, I start my new <script> tag where our code will sit:
<script src="http://code.jquery.com/jquery-1.5.min.js"></script>
<script>
$(document).ready(function () {
// our code lives here
});
</script>
</body>
</html>
1 & 2. Making the Ajax request
Inside of the $(document).ready we want to say: “when the select box changes, make an Ajax request to load the article select box”:
$('#category').change(function () {
var categoryName = $('#category').val();
// for now, let's assume that <select id="articles"> exists
// so our Ajax url could look like: select-boxes-medium.html
$('#articles').load('select-boxes-' + categoryName + '.html');
});
Here I’m using the load method to take the contents of the file I’m requesting, and squirting it straight in to the $('#article') element - which, right now, doesn’t exist. So let’s create that now.
3. Create the article select box
We’ll create an empty variable: $article, and when the category is changed for the first time, we check to see if $article is null, and if it is, we create the article select box and assign it to $article (therefore preventing it from being created again):
var $article = null;
$('#category').change(function () {
var categoryName = $('#category').val();
if ($article == null) {
$article = $('<select id="article" name="article"></select>').appendTo('form');
}
// note that now we're point to the $article variable
$article.load('select-boxes-' + categoryName + '.html');
});
Now the form is working and creating the second select box properly, all we have to do is tidy up some of the buttons, since currently the “next” button submits the form.
4. Buttons
There’s three things we need to do:
- Change the “next” submit button to a “button” button
- If “next” is clicked, pretend like the category was changed (note: this part was accidentally omitted from the screencast)
- Add a “read” button (which if we were progressively enhancing a real page, this would appear when the category was submitted the first time)
The code needs the following added to the end:
var $next = $('#next');
$next[0].setAttribute('type', 'submit'); // note: this is required due to a bug in jQuery
// note that this part is not in the screencast
$next.click(function () {
$('#category').change();
});
Now inside of the Ajax request, we change the part that creates the article select for the first time and add:
if ($article == null) {
$article = $('<select id="article" name="article"></select>').appendTo('form');
$next.remove();
$('form').append('<input type="submit" value="read »" />');
}
And that’s that.
You can check out the final product and the final working version - but please, please remember this is a contrived example, only designed to show you how easy it is to populate on select box with another.
You should follow me on Twitter here I tweet about jQuery amongst the usual tweet-splurges!
Related screencasts
Demo
If you find this demo doesn't work as expected, it's possibly due to the demo running from within an iframe. Try running the demo in it's own window.
Source Code

Play QuickTime version
Play Flash version

Lee Wilson On 11th February 2011 at 14:02
Nice example, just need a project to come along that I can use it on now.
Lee
Krzysztof Kotowicz On 11th February 2011 at 16:02
Once I’ve made a jQuery plugin that does similar things and more - you could e.g. load additional subtrees with AJAX or have all the tree supplied at once, preselect given tree nodes etc.
Take a look: http://code.google.com/p/jquery-option-tree/
Bruno Belotti On 11th February 2011 at 17:02
Thanks for sharing! Actually I already implemented a thing like this some months ago, but it’s always useful to see different approaches from your, isn’t it? :) Can’t wait to see the next one….! Cheers,
Bruno
Chris Greenhough On 14th February 2011 at 13:02
Welcome back, Remy :-)
Rozzy On 18th February 2011 at 18:02
This tutorial can be applied if you have large library of codes, snippets and modules that you want to categorize as “easy”, “medium” and “advanced”.
The tutorial is easy to understand can’t wait to try and improve it on my own, though I am still applying a little bit JQUERY on my ASP.NET projects which came to be a little bit tricky when it comes with javascript.
Thanks for sharing.
stefan On 21st February 2011 at 10:02
hi i try this example but when i open the page with IE 8 the second select box have a width of 10px and if reload the page in second box load all 3 file in list
Patrick Ryan On 26th February 2011 at 12:02
Just a point of style …
Is it better to use $(…)[0] or $(…).get(0) ?
I’ve always shied away from using the array notation as that makes an assumption about how jQuery is implemented. The other advantage of get() is that you specify a negative index, e.g. $(…).get(-1) gets the last DOM element in the jQuery object.
David Raine On 27th February 2011 at 22:02
Hi - love your work but the “populate select boxes” podcast won’t load on my iphone 3GS. Itunes just gives me the message “[...] was not copied to the iphone because it cannot be played on this iphone”. Are your podcasts now iphone 4 only? My phone is ios 4.2.1. All other jQfD podcasts are fine.
Remy On 3rd March 2011 at 19:03
@Patrick - basically, if you think you’re going to use the negative index, stick with
.get(n). If not, I’d recommend using the[n]syntax, simply because using the.getis an extra function call that you don’t need to do (if you wanted to, you could check the source code of jQuery for thegetmethod, and see it simply returnsthis[n]- so the method call is superfluous).@David - I’ve got a 3GS (and an iPhone4) so I’ll check this out myself. It maybe that I’ve upped the resolution of the video, but I started doing this in a few podcasts ago. Can you check the previous one and see if it’s okay (I’ll do this too when I get a chance). If that’s fine but this isn’t…well, I’m not sure - but I’ll definitely look in to it. Sorry! :)
QR Code Marketing On 10th March 2011 at 20:03
Nice. I can see myself using this one in the near future.
rajib ahmed On 1st April 2011 at 02:04
I guess i had this form issue last year , but i guess its security measure rather then a bug by JQuery. Because it would give power bad guys to do bad stuff using a truly amazing JQuery :)
Thanks for a great article !!
Everardo On 7th April 2011 at 14:04
Great article! Simple and clear. Cheers, Everardo
Scott Martin On 10th June 2011 at 22:06
Why don’t you just remove the next button to begin with instead of changing the attribute first? Or, why not change the next button’s name and move it to the end of the form?