¿Cuál es la mejor manera de agregar opciones a un select desde como un objeto JavaScript con jQuery?

1380

¿Cuál es el mejor método para agregar opciones a un <select> objeto JavaScript usando jQuery?

Estoy buscando algo para lo que no necesito un complemento, pero también me interesarían los complementos que están disponibles.

Esto es lo que hice:

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

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

Una solución limpia / simple:

Esta es una versión limpia y simplificada de matdumsa :

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

Cambios de matdumsa: (1) eliminó la etiqueta de cierre para la opción dentro de append () y (2) movió las propiedades / atributos a un mapa como el segundo parámetro de append ().

Darryl Hein
fuente
44
quizá de ayuda: texotela.co.uk/code/jquery/select (que era una ayuda para mí después de que me encontré con esta pregunta)
ManBugra
2
La versión limpia mencionada anteriormente solo funciona en Jquery 1.4+. Para versiones anteriores, use la respuesta de
matdumsa
{value: key} debe ser {"value": key} como se ve en la respuesta de matdumsa.
Nick P
No lo creo ya que valuees una cadena (y está codificada) que no necesita ser citada.
Darryl Hein
1
El título debería ser "¿Cuál es la mejor manera de agregar opciones a una selección de un objeto JSON con jQuery?
Dr Fred

Respuestas:

1384

Lo mismo que otras respuestas, de manera jQuery:

$.each(selectValues, function(key, value) {   
     $('#mySelect')
         .append($("<option></option>")
                    .attr("value", key)
                    .text(value)); 
});
matdumsa
fuente
99
En primer lugar, asignaría $("#mySelect")a un var, de lo contrario, llamar $("#mySelect")cada vez dentro del ciclo es muy derrochador, al igual que actualizar el DOM. Vea los puntos 3 y 6 en artzstudio.com/2009/04/jquery-performance-rules/…
Patrick
77
bueno, podrías hacer var mySelect = $("#mySelect") outside of the cada bucle. Eso sería mucho más eficiente. Vea la respuesta de Carl a continuación
Patrick
17
Mi recomendación para un mejor estilo jQuery: $ ('# mySelect') .append ($ ("<option />") .val (key) .text (value));
FAjir
10
Con la popularidad de esta respuesta, vale la pena mencionar que debe evitar las actualizaciones DOM en los bucles. jsperf.com/jquery-append-array-vs-string
jthomas
66
esta respuesta fue tanto engañoso debido a la intendation mal ... attry texten realidad son métodos de la $('<option/>')-objeto
phil294
268
var output = [];

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

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

De esta manera, "toca el DOM" solo una vez.

No estoy seguro de si la última línea se puede convertir a $ ('# mySelect'). Html (output.join ('')) porque no conozco las partes internas de jQuery (tal vez hace algún análisis en el html () método)

gpilotino
fuente
20
Obviamente, su método es el más rápido que la respuesta 'correcta' anterior, ya que también utiliza menos jQuery.
Teej
44
la línea "$ ('# mySelect'). get (0) .innerHTML = output.join ('');" funciona en Chrome y FF3.x pero no en IE7 por lo que puedo decir
blu
19
Esto se rompe si keytiene algunas citas o >, <en él.
nickf
3
Y, si tengo dos opciones que no quiero perder. ¿Cómo puedo agregar estos nuevos valores de opciones a los existentes?
VansFannel
66
Una pequeña mejora es concatenar usando la combinación en lugar del signo más, así: output.push ('<option value = "', key, '">', value, '</option>');
MM.
202

Esto es un poco más rápido y más limpio.

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
fuente
3
Perfecto. Para agregarlo, se podrían agregar atributos adicionales para la selección. $ .each (selectValues, function (id, value, text) {$ ('# mySelect'). append ($ ("<option />", {id: id value: value, text: text}));} );
idok
45
Piensa que será una mejor idea almacenar en caché `$ ('# mySelect')`, de modo que busque solo una vez antes del ciclo. Actualmente está buscando en el DOM el elemento para cada opción.
Sushanth -
@ Sushanth: ¿qué tan grande es el éxito de rendimiento si el conjunto es pequeño?
ckarbass
3
@ckarbass: depende del tamaño de tu DOM. Potencialmente grande y muy poco esfuerzo para asignarlo a una variable, ¡mucho menos que escribir un comentario en SO!
Nick H247
97

jQuery

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

JavaScript vainilla

var list = document.getElementById("selectList");
for(var i in items) {
  list.add(new Option(items[i].text, items[i].value));
}
Carl Hörberg
fuente
44
Nunca he oído hablar del Optionobjeto antes. ¿Está integrado en todos los navegadores?
Darryl Hein
2
Intenté usarlo new Option, pero descubrí que no funcionaba en IE6 y 7. No tengo una razón para hacerlo, pero muchas de las opciones jQuery completas funcionaron.
Darryl Hein
Buena manera de agregar selección también. new Option('display', value, true)
Boatcoder
@ Mark0978 en realidad es new Option('display', value, true, true)( javascriptkit.com/jsref/select.shtml )
Carl Hörberg
38

Si no tiene que admitir versiones antiguas de IE, usar el Optionconstructor es claramente el camino a seguir, una solución legible y eficiente :

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

Es equivalente en funcionalidad a, pero más limpio que:

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

Esto se ve mejor, proporciona legibilidad, pero es más lento que otros métodos.

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

Si desea velocidad, la forma más rápida (¡probada!) Es usar matriz, no concatenación de cadenas, y usar solo una llamada anexa.

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

$('#selectBox').append(auxArr.join(''));
m1sfit
fuente
¿No significa esto que la forma "más rápida" sería insertar las diversas partes de la cadena como elementos individuales de la matriz también, en lugar de concatenar las que constituyen cada opción antes de insertarlas en la matriz, ya que todas se unirán como una al final?
bitooleano
22

Un refinamiento de la respuesta de @ joshperry :

Parece que .append simple también funciona como se esperaba,

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

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

o más corto

$("#mySelect").append(
  $.map(selectValues, (v,k) => $("<option>").val(k).text(v))
  // $.map(selectValues, (v,k) => new Option(v, k)) // using plain JS
);
Сухой27
fuente
¿podría utilizar alternativamente $.weakmappara permitir?GC
Chef_Code
2
Puntos de bonificación por elegancia: ¡usando apropiadamente la map()construcción, combinada con la propiedad de append()agregar una matriz de objetos correctamente!
Jochem Schulenklopper
@joshperry Estoy un poco decepcionado ya que esperaba una corrección / actualización técnica.
Сухой27
20

Todas estas respuestas parecen innecesariamente complicadas. Todo lo que necesitas es:

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

Eso es completamente compatible con navegadores cruzados.

Animismo
fuente
Debe ser new Option(value, key);? El orden de los parámetros es Opciones (text_visible_part, value_behind_the_scenes).
Bob Stein
¿No es Array push compatible con todos los navegadores? Entonces, ¿no es esto innecesariamente complicado, cuando Array push es más legible?
bitooleano
18

Tenga cuidado ... Estoy usando jQuery Mobile 1.0b2 con PhoneGap 1.0.0 en un teléfono Android 2.2 (Cyanogen 7.0.1) (T-Mobile G2) y no pude conseguir que el método .append () funcionara. Tuve que usar .html () como sigue:

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

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

He hecho algunas pruebas y creo que esto hace el trabajo más rápido. :PAGS

Teej
fuente
1
Cada uno es notoriamente lento en comparación con otras formas de lograr el mismo resultado. Esto es lo que estaba pensando y recomendaría este enfoque.
Allen Tellez
Es lamentable que el 90% de las variaciones aquí usen $ .each (). Un bucle for () puede brindarle mucho más control y beneficios de rendimiento, incluso si es menos compacto.
HoldOffHunger
15

Hay un enfoque que utiliza el enfoque de plantilla de Microsoft que actualmente se propone incluir en jQuery core. Hay más poder en el uso de plantillas, por lo que para el escenario más simple, puede no ser la mejor opción. Para obtener más detalles, consulte la publicación de Scott Gu que describe las características.

Primero incluya el archivo js de plantillas, disponible en github .

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

Siguiente configurar una plantilla

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

Luego, con sus datos, llame al método .render ()

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

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

He blogueado este enfoque con más detalle.

Nick Josevski
fuente
12

He hecho algo como esto, cargando un elemento desplegable a través de Ajax . La respuesta anterior también es aceptable, pero siempre es bueno tener la menor modificación de DOM posible para un mejor rendimiento.

Entonces, en lugar de agregar cada elemento dentro de un ciclo, es mejor recolectar elementos dentro de un ciclo y agregarlo una vez que se haya completado.

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

Añádelo,

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

o mejor

$('#select_id').html(items);
Komang
fuente
$ ('# select_id'). html (elementos); funcionó exactamente como quería. usando append sigue agregando los elementos en todos los eventos de cambio. Muchas gracias.
Dipanwita Das
10

La forma simple es:

$('#SelectId').html("<option value='0'>select</option><option value='1'>Laguna</option>");
willard macay
fuente
Ya he creado mi lista de opciones, por lo que llenar el campo de selección fue tan fácil como dice Willard.
Loony2nz
10

La mayoría de las otras respuestas usan la eachfunción para iterar sobreselectValues . Esto requiere que se invoque append para cada elemento y se active un reflujo cuando cada uno se agrega individualmente.

La actualización de esta respuesta a un método funcional más idiomático (usando JS moderno) se puede formar para llamar appendsolo una vez, con una matriz de optionelementos creados usando el mapa y un Optionconstructor de elementos.

El uso de un Optionelemento DOM debería reducir la sobrecarga de llamadas a funciones, ya que el optionelemento no necesita actualizarse después de la creación y la lógica de análisis de jQuery no necesita ejecutarse.

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

Esto se puede simplificar aún más si realiza una función de utilidad de fábrica que renovará un objeto de opción:

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

Entonces esto se puede proporcionar directamente a map:

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

Formulación previa

Debido a que appendtambién permite pasar valores como un número variable de argumentos, podemos crear la lista de optionelementos del mapa y agregarlos como argumentos en una sola llamada mediante el uso apply.

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

Parece que en versiones posteriores de jQuery, appendtambién acepta un argumento de matriz y esto se puede simplificar de alguna manera:

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

Funciona bien con jQuery 1.4.1.

Para ver el artículo completo sobre el uso de listas dinámicas con ASP.NET MVC y jQuery, visite:

Listas de selección dinámica con MVC y jQuery

H Sampat
fuente
8

Hay un problema de clasificación con esta solución en Chrome (jQuery 1.7.1) (¿Chrome ordena las propiedades de los objetos por nombre / número?) Entonces, para mantener el orden (sí, es abuso de objetos), cambié esto:

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

a esto

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

y luego $ .each se verá así:

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

En lugar de repetir el mismo código en todas partes, sugeriría que es más conveniente escribir su propia función jQuery como:

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

Luego, para agregar una opción, simplemente haga lo siguiente:

$('select').addOption('0', 'None');
Mate
fuente
¿Podrías dar más detalles?
Lunes
7

Puede iterar sobre su matriz json con el siguiente código

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

kashif
fuente
7

Aunque las respuestas anteriores son todas respuestas válidas, puede ser aconsejable agregar todas estas a un documentFragmnet primero, luego agregar ese fragmento de documento como un elemento después de ...

Vea los pensamientos de John Resig al respecto ...

Algo en la línea 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
fuente
7
  1. $.eaches más lento que un forbucle
  2. Cada vez, una selección DOM no es la mejor práctica en bucle $("#mySelect").append();

Entonces la mejor solución es la siguiente

Si los datos JSON respson

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

úsalo como

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

Otra forma de hacerlo:

var options = [];    
$.each(selectValues, function(key, value) {
    options.push($("<option/>", {
        value: key,
        text: value
    }));
});
$('#mySelect').append(options);
DiverseAndRemote.com
fuente
Veo lo que hiciste aquí ... tomaste el consejo de almacenar en caché y $('#mySelect')luego refacturaste la respuesta @rocktheroad ... lo que sea, esta es la solución más práctica
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);
}

Esto manipula el DOM solo una vez después de construir primero una cadena gigante.

Cristiano romano
fuente
puede optimizar esto aún más y evitar el uso de jQuery por completo reemplazando $("#myselect").empty().append(opts);congetElementById('myselect').innerHtml = opts;
vahanpwns
6

Eso es lo que hice con matrices bidimensionales: La primera columna es el elemento i, añadir a innerHTMLla <option>. La segunda columna es record_id i, agregue a la valuede <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();
        }
    }
Salado
fuente
Se ve bien. Lástima que no esté usando jQuery. Además, he tenido problemas antes con el método select.options.add (). No puedo recordar qué navegador y el problema exacto, pero decidí alejarme de él y dejar que jQuery se ocupe de las diferencias.
Darryl Hein
Soy un novato total con PHP y JQuerry, pero el código anterior funciona en todos los navegadores. el único problema es que no funciona bien en iPhone, publiqué una pregunta al respecto, no hubo suerte hasta ahora :( stackoverflow.com/questions/11364040/…
Salty
5

Descubrí que esto es simple y funciona muy bien.

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

El formato JSON:

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

Y el código jQuery para completar los valores del menú desplegable en el éxito de 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
fuente
3

Usando la función $ .map (), puede hacer esto de una manera más elegante:

$('#mySelect').html( $.map(selectValues, function(val, key){
    return '<option value="' + val + '">'+ key + '</option>';
}).join(''));
Dr. Fred
fuente
Eso es un poco más corto, pero el único problema es tratar con el escape de los valores val y key, lo que sí hace la respuesta aceptada.
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
fuente
2

Establezca su ID de selección HTML en la siguiente línea a continuación. Aquí mySelectse usa como id del elemento select.

   var options = $("#mySelect");

luego obtenga el objeto que es selectValues ​​en este escenario y lo establece en jquery para cada ciclo. Utilizará el valor y el texto de los objetos en consecuencia y lo agregará a las selecciones de opciones de la siguiente manera.

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

Esto mostrará el texto como la lista de opciones cuando se seleccione la lista desplegable y una vez que se seleccione un texto, se usará el valor del texto seleccionado.

P.ej.

"1": "prueba 1", "2": "prueba 2",

Desplegable,

nombre para mostrar: prueba 1 -> el valor es 1 nombre para mostrar: prueba 2 -> el valor es 2

Dulith De Costa
fuente
por favor describa un poco sobre la solución.
Vinay Prajapati
2

En realidad, para obtener un rendimiento mejorado, es mejor hacer una lista de opciones por separado y agregar la identificación.

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
fuente