1253

What is the best method for adding options to a <select> from a JavaScript object using jQuery?

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

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>');
  }
}

A clean/simple solution:

This is a cleaned up and simplified version of matdumsa's:

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

Changes from matdumsa's: (1) removed the close tag for the option inside append() and (2) moved the properties/attributes into an map as the second parameter of append().


30 답변


1265

Same as other answers, in jQuery fashion:

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


  • I would first of all assign $("#mySelect") to a var, otherwise calling $("#mySelect") every time inside the loop is very wasteful, as is updating the DOM. See points #3 and #6 at artzstudio.com/2009/04/jquery-performance-rules/… - Patrick
  • well you could just do var mySelect = $("#mySelect") outside of the each` loop. That would be much more efficient. See Carl's answer below - Patrick
  • My recommendation for a better jQuery style : $('#mySelect') .append($("<option/>") .val(key) .text(value)); - FAjir
  • With the popularity of this answer it's worth mentioning you should avoid DOM updates in loops. jsperf.com/jquery-append-array-vs-string - jthomas
  • this answer was so much misleading because of the wrong intendation... attr and text are actually methods of the $('<option/>')-object - Blauhirn

247

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)


  • You method is obviously the faster one than the 'correct' answer above since it uses less jQuery too. - Thorpe Obazee
  • 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
  • And, if I have two options that I don't want to lose. How can I append these new options values to the existing ones? - VansFannel
  • One small improvement is to concatenate using the join rather than the plus sign, like so: output.push('<option value="', key, '">', value, '</option>'); - MM.

185

This is slightly faster and cleaner.

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


  • Perfect. To add on it, additional attributes for the select could be added. $.each(selectValues, function(id,value,text) { $('#mySelect').append($("<option/>", { id: id value: value, text: text })); }); - idok
  • It think it will be a better idea to cache ` $('#mySelect')` , so that you look up only once before the loop. Currently it is searching the DOM for the element for every single option . - Sushanth --
  • @Sushanth-- how big a performance hit is this if the set is small? - ckarbass
  • @ckarbass - depends how big your DOM is. Potentially large and very little effort to assign it to a variable, considerably less than writing a comment in SO! - Nick H247

83

jQuery

var list = $("#selectList");
$.each(items, function(index, item) {
  list.append(new Option(item.text, item.value));
});

Vanilla JavaScript

var list = document.getElementById("selectList");
for(var i in items) {
  list.add(new Option(items[i].text, items[i].value));
}



33

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"));


28

This looks nicer, provides readability, but is slower than 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(''));


19

All of these answers seem unnecessarily complicated. All you need is:

var options = $('#mySelect').get(0).options;
$.each(selectValues, function(key, value) {
        options[options.length] = new Option(value, key);
});

That is completely cross browser compatible.


  • Should it be new Option(value, key); ? The parameter order is Options(text_visible_part, value_behind_the_scenes). - Bob Stein

18

@joshperry

It seems that plain .append also works as expected,

$("mySelect").append(
  $.map(selectValues, function(v,k){

    return $("<option>").val(k).text(v);
  })
);


  • could you alternatively use $.weakmap to allow for GC - Chef_Code
  • Bonus points for elegance: appropriately using the map() construct, combined with the property of append() to add an array of objects correctly! - Jochem Schulenklopper

15

Be forwarned... I am using jQuery Mobile 1.0b2 with PhoneGap 1.0.0 on an Android 2.2 (Cyanogen 7.0.1) phone (T-Mobile G2) and could not get the .append() method to work at all. I had to use .html() like follows:

var options;
$.each(data, function(index, object) {
    options += '<option value="' + object.id + '">' + object.stop + '</option>';
});

$('#selectMenu').html(options);


15

 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, I believe, does the job the fastest. :P


  • .each is notoriously slow compared to other ways of achieving the same result. This is what i was thinking and would recommend this approach. - Allen Tellez
  • It's unfortunate that 90% of the variations here use $.each(). A for() loop can give you much more control and performance benefits, even if it's less compact. - HoldOffHunger

12

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.


9

I have made something like this, loading a dropdown item via Ajax. The response above is also acceptable, but it is always good to have as little DOM modification as as possible for better performance.

So rather than add each item inside a loop it is better to collect items within a loop and append it once it's completed.

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

Append it,

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

or even better

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


  • $('#select_id').html(items); worked exactly how i wanted.using append it keeps on appending the items in all onchange event. Thank you so much. - Dipanwita Das

7

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.


7

The simple way is:

$('#SelectId').html("<option value='0'>select</option><option value='1'>Laguna</option>");


  • I've already built my options list, so populating the select field was as easy as Willard says. - Loony2nz

6

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


5

There's a sorting problem with this solution in Chrome (jQuery 1.7.1) (Chrome sorts object properties by name/number?) So to keep the order (yes, it's object abusing), I changed this:

optionValues0 = {"4321": "option 1", "1234": "option 2"};

to this

optionValues0 = {"1": {id: "4321", value: "option 1"}, "2": {id: "1234", value: "option 2"}};

and then the $.each will look like:

$.each(optionValues0, function(order, object) {
  key = object.id;
  value = object.value;
  $('#mySelect').append($('<option>', { value : key }).text(value));
}); 


5

Yet another way of doing it:

var options = [];    
$.each(selectValues, function(key, value) {
    options.push($("<option/>", {
        value: key,
        text: value
    }));
});
$('#mySelect').append(options);


  • I see what you did here... You took the advice to cache $('#mySelect') then refactored @rocktheroad answer... whatever, this is the more practical solution - Chef_Code

5

if (data.length != 0) {
    var opts = "";
    for (i in data)
        opts += "<option value='"+data[i][value]+"'>"+data[i][text]+"</option>";

    $("#myselect").empty().append(opts);
}

This manipulates the DOM only once after first building a giant string.


  • you can optimise this further and avoid the use of jQuery altogether by replacing $("#myselect").empty().append(opts); with getElementById('myselect').innerHtml = opts; - vahanpwns

5

Although the previous answers are all valid answers - it might be advisable to append all these to a documentFragmnet first, then append that document fragment as an element after...

See John Resig's thoughts on the matter...

Something along the lines of:

var frag = document.createDocumentFragment();

for(item in data.Events)
{
    var option = document.createElement("option");

    option.setAttribute("value", data.Events[item].Key);
    option.innerText = data.Events[item].Value;

    frag.appendChild(option);
}
eventDrop.empty();
eventDrop.append(frag);


5

  1. $.each is slower than a for loop
  2. Each time, a DOM selection is not the best practice in loop $("#mySelect").append();

So the best solution is the following

If JSON data resp is

[
    {"id":"0001", "name":"Mr. P"},
    {"id":"0003", "name":"Mr. Q"},
    {"id":"0054", "name":"Mr. R"},
    {"id":"0061", "name":"Mr. S"}
]

use it as

var option = "";
for (i=0; i<resp.length; i++) {
    option += "<option value='" + resp[i].id + "'>" + resp[i].name + "</option>";
}
$('#mySelect').html(option);



5

Rather than repeating the same code everywhere, I would suggest it is more desirable to write your own jQuery function like:

jQuery.fn.addOption = function (key, value) {
    $(this).append($('<option>', { value: key }).text(value));
};

Then to add an option just do the following:

$('select').addOption('0', 'None');


  • Could you elaborate ? - Mo.

4

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

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


2

I found that this is simple and works great.

for (var i = 0; i < array.length; i++) {
    $('#clientsList').append($("<option></option>").text(array[i].ClientName).val(array[i].ID));
};


2

That's what I did with two-dimensional arrays: The first column is item i, add to innerHTML of the <option>. The second column is record_id i, add to the value of the <option>:

  1. PHP

    $items = $dal->get_new_items(); // Gets data from the database
    $items_arr = array();
    $i = 0;
    foreach ($items as $item)
    {
        $first_name = $item->first_name;
        $last_name = $item->last_name;
        $date = $item->date;
        $show = $first_name . " " . $last_name . ", " . $date;
        $request_id = $request->request_id;
        $items_arr[0][$i] = $show;
        $items_arr[1][$i] = $request_id;
        $i++;
    }
    
    echo json_encode($items_arr);
    
  2. JavaScript/Ajax

            function ddl_items() {
                if (window.XMLHttpRequest) {
                    // Code for Internet Explorer 7+, Firefox, Chrome, Opera, and Safari
                    xmlhttp=new XMLHttpRequest();
                }
                else{
                    // Code for Internet Explorer 6 and Internet Explorer 5
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                }
    
                xmlhttp.onreadystatechange=function() {
                if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                    var arr = JSON.parse(xmlhttp.responseText);
                    var lstbx = document.getElementById('my_listbox');
    
                    for (var i=0; i<arr.length; i++) {
                        var option = new Option(arr[0][i], arr[1][i]);
                        lstbx.options.add(option);
                    }
                }
            };
    
            xmlhttp.open("GET", "Code/get_items.php?dummy_time=" + new Date().getTime() + "", true);
            xmlhttp.send();
        }
    }
    


  • Looks good. Too bad it's not using jQuery. Also, I've had problems before with the select.options.add() method. Can't recall which browser and the exact problem, but I decided to go a way from it and let jQuery deal with the differences. - Darryl Hein
  • im a total noob with PHP and JQuerry, but the above code is working in all browsers. the only problem - it's not working well on iPhone, i posted a question about it, no luck so far :( stackoverflow.com/questions/11364040/… - Salty

2

The JSON format:

[{
    "org_name": "Asset Management"
}, {
    "org_name": "Debt Equity Foreign services"
}, {
    "org_name": "Credit Services"
}]

And the jQuery code to populate the values to the Dropdown on Ajax success:

success: function(json) {
    var options = [];
    $('#org_category').html('');  // Set the Dropdown as Blank before new Data
    options.push('<option>-- Select Category --</option>');
    $.each(JSON.parse(json), function(i, item) {
        options.push($('<option/>',
        {
           value: item.org_name, text: item.org_name
        }));
    });
    $('#org_category').append(options);  // Set the Values to Dropdown
}


1

Using the $.map() function, you can do this in a more elegant way:

$('#mySelect').html( $.map(selectValues, function(val, key){
    return '<option value="' + val + '">'+ key + '</option>';
}).join(''));


  • That is kind of shorter, but the one problem is dealing with escaping of the val and key vars which the accepted answer does do. - Darryl Hein

0

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


0

I combine the two best answers into a great answer.

var outputConcatenation = [];

$.each(selectValues, function(i, item) {   
     outputConcatenation.push($("<option></option>").attr("value", item.key).attr("data-customdata", item.customdata).text(item.text).prop("outerHTML"));
});

$("#myselect").html(outputConcatenation.join(''));


0

<!DOCTYPE html>
<html lang="en">
<head>
  <title>append selectbox using jquery</title>
  <meta charset="utf-8">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

  <script type="text/javascript">
    function setprice(){
        var selectValues = { "1": "test 1", "2": "test 2" };
        $.each(selectValues, function(key, value) {   
     $('#mySelect')
         .append($("<option></option>")
                    .attr("value",key)
                    .text(value)); 
});

    }
  </script>
</head>
<body onload="setprice();">


      <select class="form-control" id="mySelect">
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
  </select>


</body>
</html>


  • It's good practice on Stack Overflow to add an explanation as to why your solution should work. For more information read How To Answer. - Samuel Liew

Linked


Related

Latest