views:

35660

answers:

17

What is the best method for adding options to a select from a JSON array using jQuery?

I'm looking for something that I don't need a plugin to do, but would also be interested in the plugins that are out there.

A: 

This is what I did:

selectValues = {"1":"test 1","2":"test 2"};
for (key in selectValues) {
    if (typeof(selectValues[key] == 'string') {
        $('#mySelect').append('<option value="' + key + '">' + selectValues[key] + '</option>');
    }
}
Darryl Hein
+53  A: 

Same as other answers, in jQuery fashion:

$.each(selectValues, function(key, value)
{   
     $('#mySelect').
          append($("<option></option>").
          attr("value",key).
          text(value)); 
});
matdumsa
Does not work in Safari 3.2.
zgoda
this is not the "best" way. the best (faster) way is to contruct the html output (ie. join an array into a string) then set the innerHTML of the select element. $('#mySelect').html(optionString)
gpilotino
the innertHTML trick does not work on IE!!!!
This is the only solution I tried that also worked in IE. Note you can use $('#mySelect').empty() if you want to clear all the options first.
@gpilotino - Your method doesn't encode the values like this does, and is unsafe against XSS attacks as well, so it's a trade-off going your route...I prefer not having to worry that one day a value with a quote in it will break the page :)
Nick Craver
you're right about xss and escaping (indeed i wrongly assumed that only valid key/value couples were passed). the point is that the faster method does not have code that modifies the DOM in a loop.
gpilotino
+1  A: 

matdumsa: is it wrong to do this?

$.each(selectValues, function(key, value) {
    $('#mySelect').append("<option value="' + key + '">' + value + '</option>");
});

Instead of setting attributes, I just put the full HTML string in and let jQuery deal with it...but does it?

Darryl Hein
+2  A: 

Darryl Hein: It's not bad and totally valid.. but jQuery, under the hood convert all html and internally perform the same operation everytime you give HTML to it:

http://www.slideshare.net/jeresig/jquery-internals-cool-stuff-presentation/

Slide 21 and + (from John Resig).. I suppose that it would be faster to give less html in string and more attribute setting...

matdumsa
A: 

I have made something like this load dropdown item via ajax, the response above also acceptable but it always good to have DOM modification as less as it can for better performance.

so rather than add each item inside a loop it is better to collect item within a loop and append it once its completed.

$(data).each(function(){
 ... collect items
})

append it

$('#select_id').append(items);

or even better

$('#select_id').html(items);
Ariel
+3  A: 

Using DOM Elements Creator plugin (my favorite):

$.create('option', {'value': 'val'}, 'myText').appendTo('#mySelect');

Using the Option constructor (not sure about browser support):

$(new Option('myText', 'val')).appendTo('#mySelect');

Using document.createElement (avoiding extra work parsing HTML with $("<option></option>")):

$('#mySelect').append($(document.createElement("option")).
                        attr("value","val").text("myText"));
Nickolay
+1  A: 

I have similar problems but with a little difference. In my case, I want to remove all options, then send a get request to get a new options in JSON format, then add the new options to the select (now empty).

Using http://www.texotela.co.uk/code/jquery/select/ plugins is working flawlessly in Firefox. My client also wants it to work in IE and Safari. Problems arise when I implement jQuery validation plugins in the same page. I'm using a validation plugin as well.

In firefox no problems at all. But in IE and safari, the select box stays empty after JSON data received. I have tried many methods mentioned on this page and other sources I found in google. I have tried select.add, select.options.add, creating string var option_text = '<option value="val">text</option>' then add it to select: $("select").html(option_text). All methods worked on Firefox, but none worked on Safari and IE.

In my last attempt, I change the server side response from JSON to a complete select element. When I want the select to change, I empty the select's parent, do AJAX get request, then add the data response to the container. This method worked in all 3 browser (Firefox, IE, Safari). (Note that this is Windows version of Safari.) I'm still waiting my client's response on Mac's Safari.

This is my code snippets:

var loading_image = '<img src="<?php echo FULL_PATH_TO_loading.gif'; ?>" alt="loading..." id="loading-image" />';
//handle date change and available time
function do_update_time($){
  $("#appointment_time_container").after(loading_image);
  var url = 'http://PATH_TO_LOAD_NEW_OPTION';
  $.get(url,
    {},
    function(data){
      $("#loading-image").hide().remove();
      $("#appointment_time_container").html(data);
    });
};

Hope this code helps others that feel the pain of IE's and Safari's quirks.

Donny Kurnia
+18  A: 
var output = [];

$.each(selectValues, function(key, value)
{
  output.push('<option value="'+ key +'">'+ value +'</option>');
});

$('#mySelect').html(output.join(''));

In this way you "touch the DOM" only one time.

I'm not sure if the latest line can be converted into $('#mySelect').html(output.join('')) because I don't know jquery internals (maybe it does some parsing in the html() method)

gpilotino
You method is obviously the faster one than the 'correct' answer above since it uses less jQuery too.
Thorpe Obazee
Can you explain what the get(0) is? I tried looking in the documentation of jQuery but just can't find it :(
AntonioCS
as $(* selector *) function returns a reference to the jquery object (a collection), get(0) (or simply [0]) return the first pure HTML DOM object (you can apply non jquery methods on it): docs.jquery.com/Core/get
gpilotino
the line "$('#mySelect').get(0).innerHTML = output.join('');" works in Chrome and FF3.x but not in IE7 as far as I can tell
blu
This breaks if the `key` has some quotes or `>, <` in it.
nickf
if the key has some quotes or < or > then is not valid html. native innerHTML is faster than using jquery html().
gpilotino
+4  A: 
 var output = [];
 var length = data.length;
 for(var i=0; i < length; i++)
 {
    output[i++] = '<option value="'+ data[i].start +'">'+ data[i].start +'</option>';
 }

 $('#choose_schedule').get(0).innerHTML = output.join('');

I've done a few tests and this is, I believe does the job the fastest :P

Thorpe Obazee
+1  A: 

$('#mySelect').html(optionString) This is really good option to put multiple options in select box. I have one question that, What is the method to remove existing options from the select box using JQurey.

In general way, we are using like this var select = document.getElementById("mySelect"); 30 select.options.length = 0;

Amit
if you have a question. Click the "Ask a question" button at the top. Dont answer a question wih another question!
redsquare
redsquare is right, but Amit, all you need to do with jQuery is: $('#mySelect').empty(); to remove all of the options within a select.
Darryl Hein
+2  A: 

this looks nicer, provides readability, but is slower then other methods

$.each(selectData, function(i, option)
{
 $("<option/>").val(option.id).text(option.title).appendTo("#selectBox");
});

if you want speed, the fastest (tested!) way is this, using array, not string concatenation, and using only one append call

auxArr = [];
$.each(selectData, function(i, option)
{
    auxArr[i] = "<option value='" + option.id + "'>" + option.title + "</option>";
}

$('#selectBox').append(auxArr.join(''));
m1sfit
+1  A: 
function populateDropdown(select, data) {   
    select.html('');   
    $.each(data, function(id, option) {   
        select.append($('<option></option>').val(option.value).html(option.name));   
    });          
}   

It works well with jQuery 1.4.1.

For complete article for using dynamic lists with ASP.NET MVC & jQuery visit: http://www.codecapers.com/post/Dynamic-Select-Lists-with-MVC-and-jQuery.aspx

H Sampat
A: 

simple way is

$('#SelectId').html("<option value='0'>select </option><option value='1'>Laguna</option>");
willard macay
+5  A: 

This should be like answer, but slightly faster and cleaner

$.each(selectValues, function(key, value)
{   
     $('#mySelect').
          append($("<option/>"), {
              value: key,
              text: value});
});
rocktheroad
A: 

There's an approach using the Microsoft Templating approach that's currently under proposal for inclusion into jQuery core. There's more power in using the templating so for the simplest scenario it may not be the best option. For more details see Scott Gu's post outlining the features.

First include the templating js file, available from github.

<script src="Scripts/jquery.tmpl.js" type="text/javascript" />

Next set-up a template

<script id="templateOptionItem" type="text/html">
    <option value=\'{{= Value}}\'>{{= Text}}</option>
</script>

Then with your data call the .render() method

var someData = [
    { Text: "one", Value: "1" },
    { Text: "two", Value: "2" },
    { Text: "three", Value: "3"}];

$("#templateOptionItem").render(someData).appendTo("#mySelect");

I've blogged this approach in more detail.

Nick Josevski
A: 

You can just iterate over your json array with the following code

$('<option/>').attr("value","someValue").text("Option1").appendTo("#my-select-id");

kashif
A: 

A compromise of sorts between the top two answers, in a "one-liner":

$.fn.append.apply($('mySelect'),
    $.map(selectValues, function(val, idx) {
        return $("<option/>")
            .val(val.key)
            .text(val.value);
    })
);

Builds up an array of Option elements using map and then appends them all to the Select at once by using apply to send each Option as a separate argument on the append function.

joshperry