JSON Selects | Comments (5)
Posted in Code on 19th July 2006, 2:13 pm by Stuart
This is a really simple method to populate select boxes dynamically using JSON as the source of the data. This script is really just a basic example so that you can see how easy it is to work with JSON in this way, you could take this and adapt it quite simply to get data over XHR for example.
It’s also a follow on to my previous post (Bug when creating select options using innerHTML in IE) as it demonstrates using pure DOM methods to create the select box options.
Don’t forget that in the real world you would also need to allow for when javascript is not available to the user-agent and provide a means to update the subsequent select on page refresh.
var objSelData = {
guitars:{
"GSG":"Gibson SG",
"GLP":"Gibson Les Paul",
"FSC":"Fender Stratocaster",
"FTC":"Fender Telecaster"
},
keyboards:{
"HRP":"Harpsichord",
"HOR":"Hammond Organ",
"FRO":"Fender Rhodes",
"WEP":"Wurlitzer EP200"
}
};
var jsel = {
// config for first option text e.g '-' or 'Please Select'
blankOption: '-',
// Removes the children of the target element
removeChildren: function(elm) {
while(elm.hasChildNodes()){
elm.removeChild(elm.firstChild);
}
},
// Gets current selected value
getSelVal: function(objSrcSelect) {
if (objSrcSelect.nodeName == 'SELECT'){
var children = objSrcSelect.childNodes;
for (var i=0, j=children.length; i<j; i++) {
if (children[i].selected === true) {
return children[i].value;
}
}
} else {
return false;
}
},
// Creates select options
createOpt: function(strVal,strText,objTargetSelect) {
var opt = document.createElement(’OPTION’);
opt.setAttribute(’value’,strVal);
var text = document.createTextNode(strText);
opt.appendChild(text);
objTargetSelect.appendChild(opt);
},
// Loads in the data to the select based on the previous selection
loadData: function(objData, objSrcSelect, objTargetSelect) {
var val = jsel.getSelVal(objSrcSelect);
jsel.removeChildren(objTargetSelect);
jsel.createOpt(”,jsel.blankOption,objTargetSelect);
for(prop in objData[val]) {
if (val) {
jsel.createOpt(prop,objData[val][prop],objTargetSelect);
}
}
}
}
// Use your choice of addevent here…
window.onload = function() {
var type = document.getElementById(’type’);
var instr = document.getElementById(’instr’);
// …and here
type.onchange = function () { jsel.loadData(objSelData, type, instr); return false; }
if (jsel.getSelVal(type) != ”) {
jsel.loadData(objSelData, type, instr);
}
};
The way it works is quite simple. The when the first select box is changed this triggers an onchange event which then grabs the value of the currently selected option. It then look find the data that corresponds with that value in the JSON object, blows away the current options in the second select and creates and appends new options to the second select based on that data.
The core operation is in the for loop:
for(prop in objData[val]) {
if (val) {
jsel.createOpt(prop,objData[val][prop],objTargetSelect);
}
}
objData[val] is the same as saying objData.guitars when the variable val equates to guitars. If you’ve not come across square bracket notation before it’s the only way you can access object properties with a variable, and as such allows you to loop through the data and access your data to populate the select.
For this week’s homework I would suggest you play around with it and try implementing a xhr solution.
Please check out the JSON Selects example page.

The removeChildren() is a good generic function but could be quite expensive. You could also remove all options by setting the options.length property to 0, or by simply setting innerHTML to an empty string.
Sometimes the old school form stuff is much faster and straight forward. If I were a fetishist I’d do a benchmark, but the weather is too nice.
@Chris: You make some good points there and those are some viable alternatives. I am not so anal that I must use the DOM for everything, and I can see that that setting the innerHTML to an empty string would be much more likely to be faster compared to my loop.
Nice!
But… Shouldn’t this
keyboards:{
"HRP":"Harpsichord",
"HOR":"Hammond Organ",
"FRO":"Fender Rhodes",
"WEP":"Wurlitzer EP200"
}
be like this?
keyboards:{
HRP:"Harpsichord",
HOR:"Hammond Organ",
FRO:"Fender Rhodes",
WEP:"Wurlitzer EP200"
}
I mean, those are attribute names in an object, not keys in a hash, right?
@Ismael: Thanks for the comment. Re: the quotes: That’s not the case, in valid JSON, property names are always quoted.
Wow, that’s kinda shocking! I guess I’ll have to go through thousands of lines of code I’ve made
(it works, though)