Qual é a melhor maneira de adicionar opções a uma seleção como um objeto JavaScript com o jQuery?

1380

Qual é o melhor método para adicionar opções a um <select>objeto JavaScript usando jQuery?

Estou procurando algo que não precise de um plug-in para fazer, mas também estaria interessado nos plug-ins disponíveis.

Isto é o que eu fiz:

selectValues = { "1": "test 1", "2": "test 2" };

for (key in selectValues) {
  if (typeof (selectValues[key] == 'string') {
    $('#mySelect').append('<option value="' + key + '">' + selectValues[key] + '</option>');
  }
}

Uma solução limpa / simples:

Esta é uma versão limpa e simplificada do matdumsa's :

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

Alterações de matdumsa: (1) removeu a tag close da opção dentro de append () e (2) moveu as propriedades / atributos para um mapa como o segundo parâmetro de append ().

Darryl Hein
fonte
4
talvez de ajuda: texotela.co.uk/code/jquery/select (era uma ajuda para mim, depois me deparei com esta questão)
ManBugra
2
A versão limpa listada acima funciona apenas no Jquery 1.4+. Para versões mais antigas usar aquele em resposta de matdumsa
Thedric Walker
{value: key} deve ser {"value": key} como visto na resposta de matdumsa.
Nick P
Eu não acredito valuenisso, uma vez que é uma string (e codificada) que não precisa ser citada.
Darryl Hein
1
O título deve ser "Qual é a melhor maneira de adicionar opções a uma seleção de um objeto JSON com jQuery?"
Dr. Fred

Respostas:

1384

O mesmo que as outras respostas, da maneira jQuery:

$.each(selectValues, function(key, value) {   
     $('#mySelect')
         .append($("<option></option>")
                    .attr("value", key)
                    .text(value)); 
});
matdumsa
fonte
99
Antes de tudo, eu atribuiria $("#mySelect")a um var, caso contrário, chamar $("#mySelect")toda vez que o loop for muito inútil, assim como atualizar o DOM. Veja os pontos 3 e 6 em artzstudio.com/2009/04/jquery-performance-rules/…
Patrick
7
bem, você poderia fazer var mySelect = $("#mySelect") outside of the cada loop. Isso seria muito mais eficiente. Veja a resposta de Carl abaixo
Patrick
17
Minha recomendação para um estilo jQuery melhor: $ ('# mySelect') .append ($ ("<option />") .val (key) .text (value));
FAjir
10
Com a popularidade desta resposta, vale a pena mencionar que você deve evitar atualizações do DOM em loops. jsperf.com/jquery-append-array-vs-string
jthomas
6
Essa resposta foi muito enganosa por causa da intendation errado ... attre textsão realmente métodos da $('<option/>')-object
phil294
268
var output = [];

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

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

Dessa forma, você "toca no DOM" apenas uma vez.

Não tenho certeza se a última linha pode ser convertida em $ ('# mySelect'). Html (output.join ('')) porque não conheço elementos internos do jQuery (talvez faça alguma análise no html () método)

gpilotino
fonte
20
Seu método é obviamente o mais rápido que a resposta 'correta' acima, pois também usa menos jQuery.
1011 Teej
4
a linha "$ ('# mySelect'). get (0) .innerHTML = output.join ('');" funciona no Chrome e no FF3.x, mas não no IE7, tanto quanto eu posso dizer
blu
19
Isso interrompe se keyhouver algumas aspas ou >, <nele.
nickf
3
E, se eu tiver duas opções que não quero perder. Como posso acrescentar esses novos valores de opções aos existentes?
VansFannel 11/11/11
6
Uma pequena melhoria é concatenar usando a junção em vez do sinal de mais, assim: output.push ('<option value = "', key, '">', value, '</option>');
MM.
202

Isso é um pouco mais rápido e limpo.

var selectValues = {
  "1": "test 1",
  "2": "test 2"
};
var $mySelect = $('#mySelect');
//
$.each(selectValues, function(key, value) {
  var $option = $("<option/>", {
    value: key,
    text: value
  });
  $mySelect.append($option);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="mySelect"></select>

rocktheroad
fonte
3
Perfeito. Para adicionar, atributos adicionais para a seleção podem ser adicionados. $ .each (selectValues, function (id, value, text) {$ ('# mySelect'). append ($ ("<opção />", {id: valor da id: valor, texto: texto}));} );
Idok
45
Acha que será uma idéia melhor armazenar em cache `$ ('# mySelect')`, para que você procure apenas uma vez antes do loop. Atualmente, ele está pesquisando no DOM o elemento para todas as opções.
Sushanth -
@ Sushanth-- qual o tamanho de um desempenho atingido se o conjunto for pequeno?
ckarbass
3
@ckarbass - depende do tamanho do seu DOM. Esforço potencialmente grande e muito pouco para atribuí-lo a uma variável, consideravelmente menos do que escrever um comentário no SO!
Nick H247
97

jQuery

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

JavaScript de baunilha

var list = document.getElementById("selectList");
for(var i in items) {
  list.add(new Option(items[i].text, items[i].value));
}
Carl Hörberg
fonte
4
Nunca ouvi falar do Optionobjeto antes. Isso está embutido em todos os navegadores?
Darryl Hein
2
Tentei usar new Option, mas descobri que não funcionava no IE6 e 7. Não tenho uma razão para isso, mas muitas das opções completas do jQuery funcionaram.
Darryl Hein
Ótima maneira de adicionar a seleção também. new Option('display', value, true)
boatcoder
@ Mark0978 Na verdade, é new Option('display', value, true, true)( javascriptkit.com/jsref/select.shtml )
Carl Hörberg
38

Se você não precisa oferecer suporte a versões antigas do IE, usar o Optionconstrutor é claramente o caminho a seguir, uma solução legível e eficiente :

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

É uma funcionalidade equivalente a, mas mais limpa que:

$("<option></option>").attr("value", "val").text("myText")).appendTo('#mySelect');
Nickolay
fonte
31

Isso parece melhor, fornece legibilidade, mas é mais lento que outros métodos.

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

Se você deseja velocidade, a maneira mais rápida (testada!) É essa, usando a matriz, não a concatenação de cadeias e usando apenas uma chamada anexada.

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

$('#selectBox').append(auxArr.join(''));
m1sfit
fonte
Isso não significa que a maneira "mais rápida" seria inserir também as várias partes da string como itens individuais da matriz, em vez de concatenar as que constituem todas as opções antes de inserir na matriz, pois todas elas serão unidas como uma no final?
bitoolean 17/01/19
22

Um refinamento da resposta de @ joshperry mais antiga :

Parece que .append simples também funciona conforme o esperado,

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

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

ou mais curto,

$("#mySelect").append(
  $.map(selectValues, (v,k) => $("<option>").val(k).text(v))
  // $.map(selectValues, (v,k) => new Option(v, k)) // using plain JS
);
Сухой27
fonte
você poderia usar como alternativa $.weakmappara permitirGC
Chef_Code
2
Pontos de bônus por elegância: usando adequadamente a map()construção, combinada com a propriedade de append()para adicionar uma matriz de objetos corretamente!
Jochem Schulenklopper 2/17/17
@joshperry Estou meio decepcionado, pois esperava correção / atualização técnica.
Сухой27
20

Todas essas respostas parecem desnecessariamente complicadas. Tudo o que você precisa é:

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

Isso é completamente compatível com vários navegadores.

Animismo
fonte
Deveria ser new Option(value, key);? A ordem dos parâmetros é Opções (text_visible_part, value_behind_the_scenes).
22815 Bob Stein
O Array não é compatível com vários navegadores? Então, isso não é desnecessariamente complicado quando o Array Push é mais legível?
bitoolean 17/01/19
18

Esteja avisado ... estou usando o jQuery Mobile 1.0b2 com PhoneGap 1.0.0 em um telefone Android 2.2 (Cyanogen 7.0.1) (T-Mobile G2) e não consegui obter o método .append () para funcionar. Eu tive que usar .html () da seguinte maneira:

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

$('#selectMenu').html(options);
Jack Holt
fonte
18
 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('');

Fiz alguns testes e, acredito, isso faz o trabalho mais rápido. : P

Teej
fonte
1
.each é notoriamente lento em comparação com outras maneiras de obter o mesmo resultado. Isto é o que eu estava pensando e recomendaria esta abordagem.
Allen Tellez
É lamentável que 90% das variações aqui usem $ .each (). Um loop for () pode oferecer muito mais benefícios de controle e desempenho, mesmo que seja menos compacto.
HoldOffHunger
15

Existe uma abordagem usando a abordagem Microsoft Templating que está atualmente sob proposta para inclusão no núcleo do jQuery. Há mais poder no uso do modelo; portanto, para o cenário mais simples, pode não ser a melhor opção. Para mais detalhes, consulte a publicação de Scott Gu, descrevendo os recursos.

Primeiro, inclua o arquivo js do modelo, disponível no github .

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

Próxima configuração de um modelo

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

Em seguida, com seus dados, chame o método .render ()

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

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

Eu escrevi sobre essa abordagem em mais detalhes.

Nick Josevski
fonte
12

Eu fiz algo parecido com isto, carregando um item suspenso via Ajax . A resposta acima também é aceitável, mas é sempre bom ter o mínimo de modificação do DOM possível para obter melhor desempenho.

Portanto, em vez de adicionar cada item dentro de um loop, é melhor coletar itens dentro de um loop e anexá-lo assim que estiver concluído.

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

Anexá-lo,

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

ou melhor ainda

$('#select_id').html(items);
Komang
fonte
$ ('# select_id'). html (itens); funcionou exatamente como eu queria. Usando o apêndice, ele continua anexando os itens em todo o evento onchange. Muito obrigado.
Dipanwita Das
10

A maneira mais simples é:

$('#SelectId').html("<option value='0'>select</option><option value='1'>Laguna</option>");
willard macay
fonte
Já construí minha lista de opções, portanto, preencher o campo de seleção foi tão fácil quanto Willard diz.
Loony2nz
10

A maioria das outras respostas usa a eachfunção para iterar sobre o selectValues. Isso requer que o apêndice seja chamado para cada elemento e um reflow é acionado quando cada um é adicionado individualmente.

A atualização dessa resposta para um método funcional mais idiomático (usando JS moderno) pode ser formada para chamar appendapenas uma vez, com uma matriz de optionelementos criados usando o mapa e um Optionconstrutor de elementos.

O uso de um Optionelemento DOM deve reduzir a sobrecarga da chamada de função, pois o optionelemento não precisa ser atualizado após a criação e a lógica de análise do jQuery não precisa ser executada.

$('mySelect').append($.map(selectValues, (k, v) => new Option(k, v)))

Isso pode ser simplificado ainda mais se você criar uma função de utilitário de fábrica que atualizará um objeto de opção:

const newoption = (...args) => new Option(...args)

Então isso pode ser fornecido diretamente para map:

$('mySelect').append($.map(selectValues, newoption))

Formulação anterior

Como appendtambém permite a passagem de valores como um número variável de argumentos, podemos pré-criar a lista de optionelementos mapeados e anexá-los como argumentos em uma única chamada usando apply.

$.fn.append.apply($('mySelect'), $.map(selectValues, (k, v) => $("<option/>").val(k).text(v)));

Parece que nas versões posteriores do jQuery, appendtambém aceita um argumento de matriz e isso pode ser simplificado um pouco:

$('mySelect').append($.map(selectValues, (k, v) => $("<option/>").val(k).text(v)))
joshperry
fonte
10
function populateDropdown(select, data) {   
    select.html('');   
    $.each(data, function(id, option) {   
        select.append($('<option></option>').val(option.value).html(option.name));   
    });          
}   

Funciona bem com o jQuery 1.4.1.

Para obter o artigo completo sobre o uso de listas dinâmicas com o ASP.NET MVC e o jQuery, visite:

Listas de seleção dinâmica com MVC e jQuery

H Sampat
fonte
8

Há um problema de classificação com esta solução no Chrome (jQuery 1.7.1) (o Chrome classifica as propriedades do objeto por nome / número?) Então, para manter a ordem (sim, é um abuso de objeto), mudei isso:

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

para isso

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

e então o $ .each se parecerá com:

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

Em vez de repetir o mesmo código em todos os lugares, sugiro que seja mais desejável escrever sua própria função jQuery como:

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

Em seguida, para adicionar uma opção, faça o seguinte:

$('select').addOption('0', 'None');
Matt
fonte
Você poderia elaborar?
Mo
7

Você pode simplesmente iterar sua matriz json com o seguinte código

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

kashif
fonte
7

Embora as respostas anteriores sejam todas válidas - pode ser aconselhável anexar todas elas a um documentFragmnet primeiro e depois anexar esse fragmento de documento como um elemento após ...

Veja os pensamentos de John Resig sobre o assunto ...

Algo ao longo das linhas de:

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);
Stuart.Sklinar
fonte
7
  1. $.eaché mais lento que um forloop
  2. Cada vez, uma seleção DOM não é a melhor prática em loop $("#mySelect").append();

Portanto, a melhor solução é a seguinte

Se os dados JSON respforem

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

use-o como

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

Ainda outra maneira de fazer isso:

var options = [];    
$.each(selectValues, function(key, value) {
    options.push($("<option/>", {
        value: key,
        text: value
    }));
});
$('#mySelect').append(options);
DiverseAndRemote.com
fonte
Eu vejo o que você fez aqui ... Você levou o conselho a cache de $('#mySelect')resposta @rocktheroad então reformulado ... seja qual for, esta é a solução mais prática
Chef_Code
6
if (data.length != 0) {
    var opts = "";
    for (i in data)
        opts += "<option value='"+data[i][value]+"'>"+data[i][text]+"</option>";

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

Isso manipula o DOM apenas uma vez após a construção de uma cadeia gigante.

Christian Roman
fonte
você pode otimizar isso ainda mais e evitar o uso de jQuery por completo, substituindo $("#myselect").empty().append(opts);comgetElementById('myselect').innerHtml = opts;
vahanpwns
6

Isso é o que eu fiz com matrizes bidimensionais: A primeira coluna é item i, adicione a innerHTMLdo <option>. A segunda coluna é record_id i, adicione à valuedo <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();
        }
    }
Salgado
fonte
Parece bom. Pena que não está usando jQuery. Além disso, já tive problemas com o método select.options.add (). Não me lembro qual navegador e o problema exato, mas decidi ir além e deixar o jQuery lidar com as diferenças.
precisa saber é o seguinte
sou um noob total com PHP e JQuerry, mas o código acima está funcionando em todos os navegadores. o único problema - ele não está funcionando bem no iPhone, eu postei uma pergunta sobre ele, sem sorte até agora :( stackoverflow.com/questions/11364040/…
Salgado
5

Eu achei que isso é simples e funciona muito bem.

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

O formato JSON:

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

E o código jQuery para preencher os valores para o sucesso do menu suspenso no Ajax:

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
}
MJ
fonte
3

Usando a função $ .map (), você pode fazer isso de uma maneira mais elegante:

$('#mySelect').html( $.map(selectValues, function(val, key){
    return '<option value="' + val + '">'+ key + '</option>';
}).join(''));
Dr. Fred
fonte
Isso é um pouco mais curto, mas o único problema é lidar com o escape dos val e key vars que a resposta aceita realmente faz.
Darryl Hein
2
<!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>
Satyendra Yadav
fonte
2

Defina seu ID de seleção HTML na seguinte linha abaixo. Aqui mySelecté usado como o ID do elemento de seleção.

   var options = $("#mySelect");

obtenha o objeto que é o selectValues ​​neste cenário e o defina no jquery para cada loop. Ele usará o valor e o texto dos objetos de acordo e o anexará nas seleções de opções da seguinte maneira.

$.each(selectValues, function(val, text) {
            options.append(
             $('<option></option>').val(val).html(text)
          );
      });

Isso exibirá o texto como a lista de opções quando a lista suspensa estiver selecionada e uma vez que o texto seja selecionado, o valor do texto selecionado será usado.

Por exemplo.

"1": "teste 1", "2": "teste 2",

Suspenso,

nome para exibição: teste 1 -> o valor é 1 nome para exibição: teste 2 -> o valor é 2

Dulith De Costa
fonte
descreva um pouco sobre a solução.
Vinay Prajapati
2

Na verdade, para obter o desempenho aprimorado, é melhor fazer a lista de opções separadamente e anexar para selecionar o ID.

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

http://learn.jquery.com/performance/append-outside-loop/

shohan
fonte