Jaki jest najlepszy sposób dodawania opcji do wyboru jako obiektu JavaScript w jQuery?

1379

Jaka jest najlepsza metoda dodawania opcji do <select>obiektu JavaScript za pomocą jQuery?

Szukam czegoś, do czego nie potrzebuję wtyczki, ale chciałbym również zainteresować wtyczkami, które tam są.

Oto co zrobiłem:

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

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

Czyste / proste rozwiązanie:

To jest oczyszczona i uproszczona wersja Matdumsa :

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

Zmiany w stosunku do matdumsa: (1) usunęła tag zamykający dla opcji wewnątrz append () i (2) przeniosła właściwości / atrybuty na mapę jako drugi parametr append ().

Darryl Hein
źródło
4
może z pomocy: texotela.co.uk/code/jquery/select (była to dla mnie pomoc po tym, jak
natknąłem
2
Oczyszczona wersja wymieniona powyżej działa tylko w Jquery 1.4+. W przypadku starszych wersji użyj tej z odpowiedzi
Matdumsy
{wartość: klucz} powinna być {„wartość”: klucz}, jak widać w odpowiedzi Matdumsy.
Nick P
Nie wierzę w to, ponieważ valuejest to ciąg (i zakodowany na stałe), który nie musi być cytowany.
Darryl Hein
1
Zamiast tego tytuł powinien brzmieć „Jaki jest najlepszy sposób dodawania opcji do wyboru z obiektu JSON z jQuery?”
Dr Fred

Odpowiedzi:

1383

Tak samo jak inne odpowiedzi, w jQuery:

$.each(selectValues, function(key, value) {   
     $('#mySelect')
         .append($("<option></option>")
                    .attr("value", key)
                    .text(value)); 
});
matdumsa
źródło
99
Przede wszystkim chciałbym przypisać $("#mySelect")do var, w przeciwnym razie wywoływanie za $("#mySelect")każdym razem w pętli jest bardzo marnotrawstwem, podobnie jak aktualizowanie DOM. Zobacz punkty 3 i 6 w artzstudio.com/2009/04/jquery-performance-rules/…
Patrick
7
cóż, możesz po prostu zrobić var mySelect = $("#mySelect") outside of the każdą pętlę. Byłoby to znacznie bardziej wydajne. Zobacz odpowiedź Carla poniżej
Patrick
17
Moja rekomendacja dla lepszego stylu jQuery: $ ('# mySelect') .append ($ ("<opcja />") .val (klucz) .text (wartość));
FAjir
10
Przy popularności tej odpowiedzi warto wspomnieć, że należy unikać aktualizacji DOM w pętlach. jsperf.com/jquery-append-array-vs-string
jthomas
6
ta odpowiedź była tak bardzo myląca z powodu złej intencji ... attri textsą w rzeczywistości metodami $('<option/>')-obiektu
phil294 10.10.15
268
var output = [];

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

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

W ten sposób „dotkniesz DOM” tylko raz.

Nie jestem pewien, czy najnowszą linię można przekonwertować na $ ('# mySelect'). Html (output.join ('')), ponieważ nie znam elementów wewnętrznych jQuery (być może parsuje się w html () metoda)

gpilotino
źródło
20
Twoja metoda jest oczywiście szybsza niż „poprawna” odpowiedź powyżej, ponieważ zużywa również mniej jQuery.
Teej,
4
wiersz „$ ('# mySelect'). get (0) .innerHTML = output.join ('');” działa w Chrome i FF3.x, ale nie w IE7, o ile mogę powiedzieć
blu
19
To się psuje, jeśli keyma jakieś cytaty lub >, <w nim.
nickf
3
A jeśli mam dwie opcje, których nie chcę stracić. Jak mogę dołączyć te nowe wartości opcji do istniejących?
VansFannel,
6
Jednym drobnym ulepszeniem jest konkatenacja przy użyciu sprzężenia zamiast znaku plus, na przykład: output.push ('<option value = "', key, '">', value, '</option>');
MM.
202

Jest to nieco szybsze i czystsze.

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
źródło
3
Doskonały. Aby go dodać, można dodać dodatkowe atrybuty dla zaznaczenia. $ .each (selectValues, function (id, value, text) {$ ('# mySelect'). append ($ ("<opcja />", {id: id wartość: wartość, tekst: tekst}));} );
idok
45
Uważa, że ​​lepszym pomysłem będzie buforowanie `$ ('# mySelect')`, aby spojrzeć w górę tylko raz przed pętlą. Obecnie szuka DOM dla elementu dla każdej opcji.
Sushanth -
@ Sushanth - jak duży jest hit wydajności, jeśli zestaw jest mały?
ckarbass
3
@ckarbass - zależy od wielkości twojego DOM. Potencjalnie duży i bardzo niewielki wysiłek, aby przypisać go do zmiennej, znacznie mniej niż napisanie komentarza w SO!
Nick H247
97

jQuery

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

Waniliowy JavaScript

var list = document.getElementById("selectList");
for(var i in items) {
  list.add(new Option(items[i].text, items[i].value));
}
Carl Hörberg
źródło
4
Nigdy wcześniej nie słyszałem o Optionobiekcie. Czy to jest wbudowane we wszystkie przeglądarki?
Darryl Hein
2
Próbowałem użyć new Option, ale okazało się, że nie działa w IE6 i 7. Nie mam powodu, ale działało wiele pełnych opcji jQuery.
Darryl Hein
Dobry sposób na dodanie zaznaczenia. new Option('display', value, true)
Boatcoder
@ Mark0978 faktycznie to new Option('display', value, true, true)( javascriptkit.com/jsref/select.shtml )
Carl Hörberg
38

Jeśli nie musisz obsługiwać starych wersji IE, skorzystanie z Optionkonstruktora jest zdecydowanie najlepszym rozwiązaniem, czytelne i wydajne rozwiązanie :

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

Jego funkcjonalność jest równoważna, ale czystsza niż:

$("<option></option>").attr("value", "val").text("myText")).appendTo('#mySelect');
Nickolay
źródło
31

Wygląda to ładniej, zapewnia czytelność, ale jest wolniejsze niż inne metody.

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

Jeśli chcesz prędkości, najszybszym (przetestowanym!) Sposobem jest użycie tablicy, a nie konkatenacji łańcuchów i użycie tylko jednego wywołania append.

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

$('#selectBox').append(auxArr.join(''));
m1sfit
źródło
Czy nie oznacza to, że „najszybszym” sposobem byłoby wstawienie różnych części łańcucha jako pojedynczych elementów tablicy, zamiast łączenia wszystkich elementów tworzących każdą opcję przed wstawieniem do tablicy, ponieważ i tak wszystkie one zostaną połączone na końcu?
bitoolean
22

Udoskonalenie odpowiedzi starszego @ joshperry :

Wygląda na to, że zwykły .append działa również zgodnie z oczekiwaniami,

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

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

lub krócej

$("#mySelect").append(
  $.map(selectValues, (v,k) => $("<option>").val(k).text(v))
  // $.map(selectValues, (v,k) => new Option(v, k)) // using plain JS
);
Сухой27
źródło
czy możesz alternatywnie użyć, $.weakmapaby zezwolić naGC
Chef_Code
2
Punkty bonusowe za elegancję: odpowiednio wykorzystując map()konstrukcję, w połączeniu z właściwością append()poprawnego dodania tablicy obiektów!
Jochem Schulenklopper
@joshperry Jestem trochę rozczarowany, ponieważ spodziewałem się technicznych poprawek / aktualizacji.
Сухой27
20

Wszystkie te odpowiedzi wydają się niepotrzebnie skomplikowane. Wszystko czego potrzebujesz to:

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

To jest całkowicie kompatybilny z wieloma przeglądarkami.

Animizm
źródło
Powinno być new Option(value, key);? Zamówienie parametr jest Opcje (text_visible_part, value_behind_the_scenes).
Bob Stein
Czy Array nie jest zgodny z wieloma przeglądarkami? Czy to nie jest niepotrzebnie skomplikowane, gdy wypychanie tablicy jest bardziej czytelne?
bitoolean
18

Ostrzegam ... Używam jQuery Mobile 1.0b2 z PhoneGap 1.0.0 na telefonie z Androidem 2.2 (Cyanogen 7.0.1) (T-Mobile G2) i nie mogłem w ogóle uruchomić metody .append (). Musiałem użyć .html () w następujący sposób:

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

$('#selectMenu').html(options);
Jack Holt
źródło
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('');

Zrobiłem kilka testów i to, jak sądzę, działa najszybciej. : P

Teej
źródło
1
.each jest notorycznie wolny w porównaniu do innych sposobów osiągnięcia tego samego rezultatu. Właśnie o tym myślałem i poleciłbym to podejście.
Allen Tellez
To niefortunne, że 90% odmian tutaj używa $ .each (). Pętla for () może zapewnić znacznie większą kontrolę i wydajność, nawet jeśli jest mniej zwarta.
HoldOffHunger,
15

Istnieje podejście oparte na Microsoft Templating które jest obecnie proponowane do włączenia do rdzenia jQuery. Korzystanie z szablonów ma większą moc, więc w najprostszym scenariuszu może nie być najlepszą opcją. Aby uzyskać więcej informacji, zobacz post Scott Gu opisujący funkcje.

Najpierw dołącz plik szablonu js, dostępny z github .

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

Następnie skonfiguruj szablon

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

Następnie z danymi wywołaj metodę .render ()

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

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

Mam blogu to podejście w sposób bardziej szczegółowy.

Nick Josevski
źródło
12

Zrobiłem coś takiego, ładując przedmiot rozwijany przez Ajax . Powyższa odpowiedź jest również do przyjęcia, ale zawsze dobrze jest mieć jak najmniej modyfikacji DOM, aby uzyskać lepszą wydajność.

Dlatego zamiast dodawać każdy element w pętli, lepiej jest zbierać elementy w pętli i dołączać je po zakończeniu.

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

Dołącz to,

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

a nawet lepiej

$('#select_id').html(items);
Komang
źródło
$ ('# select_id'). html (przedmioty); działało dokładnie tak, jak chciałem. za pomocą append ciągle dodaje elementy we wszystkich wydarzeniach onchange. Dziękuję bardzo.
Dipanwita Das,
10

Prosty sposób to:

$('#SelectId').html("<option value='0'>select</option><option value='1'>Laguna</option>");
Willard Macay
źródło
Zbudowałem już listę opcji, więc wypełnienie pola wyboru było tak proste, jak mówi Willard.
Loony2nz
10

Większość innych odpowiedzi używa eachfunkcji do iteracji poselectValues . Wymaga to, aby append był wywoływany dla każdego elementu, a przepływ jest uruchamiany, gdy każdy jest dodawany indywidualnie.

Aktualizacja tej odpowiedzi do bardziej idiomatycznej metody funkcjonalnej (przy użyciu nowoczesnego JS) może być utworzona, aby wywoływać appendtylko raz, z tablicą optionelementów utworzonych za pomocą mapy i Optionkonstruktora elementów.

Użycie Optionelementu DOM powinno zmniejszyć obciążenie wywołania funkcji, ponieważ optionelement nie musi być aktualizowany po utworzeniu, a logika analizy jQuery nie musi działać.

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

Można to jeszcze bardziej uprościć, jeśli utworzysz fabryczną funkcję narzędziową, która utworzy obiekt opcji:

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

Następnie można to przekazać bezpośrednio do map:

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

Poprzednie sformułowanie

Ponieważ appendpozwala również na przekazywanie wartości jako zmiennej liczby argumentów, możemy wstępnie przygotować listę optionelementów map i dołączyć je jako argumenty w jednym wywołaniu za pomocą apply.

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

Wygląda na to, że w późniejszych wersjach jQuery appendakceptuje również argument tablicowy, co można nieco uprościć:

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

Działa dobrze z jQuery 1.4.1.

Aby zapoznać się z pełnym artykułem dotyczącym korzystania z list dynamicznych w programie ASP.NET MVC i jQuery, odwiedź:

Dynamiczne listy wyboru z MVC i jQuery

H Sampat
źródło
8

Występuje problem z sortowaniem tego rozwiązania w przeglądarce Chrome (jQuery 1.7.1) (Chrome sortuje właściwości obiektu według nazwy / numeru?) Aby zachować porządek (tak, obiekt nadużywa), zmieniłem to:

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

do tego

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

a następnie $ .each będzie wyglądać następująco:

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

Zamiast powtarzać wszędzie ten sam kod, sugerowałbym, że bardziej pożądane jest napisanie własnej funkcji jQuery, takiej jak:

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

Następnie, aby dodać opcję, wykonaj następujące czynności:

$('select').addOption('0', 'None');
Matt
źródło
Czy mógłbyś opracować?
Pon.
7

Możesz po prostu iterować tablicę json za pomocą następującego kodu

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

kashif
źródło
7

Chociaż wszystkie poprzednie odpowiedzi są poprawnymi odpowiedziami - może być wskazane dołączenie ich wszystkich do documentFragmnet, a następnie dołączenie tego fragmentu dokumentu jako elementu po ...

Zobacz przemyślenia Johna Resiga na ten temat ...

Coś w stylu:

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
źródło
7
  1. $.each jest wolniejszy niż a for pętla
  2. Za każdym razem wybór DOM nie jest najlepszą praktyką w pętli $("#mySelect").append();

Więc najlepsze rozwiązanie jest następujące

Jeśli dane JSON respto

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

użyj go jako

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

Jeszcze inny sposób na zrobienie tego:

var options = [];    
$.each(selectValues, function(key, value) {
    options.push($("<option/>", {
        value: key,
        text: value
    }));
});
$('#mySelect').append(options);
DiverseAndRemote.com
źródło
Widzę, co tutaj zrobiłeś ... Skorzystałeś z porady, aby $('#mySelect')zapisać w pamięci podręcznej, a następnie ponownie przeanalizowałeś odpowiedź @rocktheroad ... cokolwiek, to jest bardziej praktyczne rozwiązanie
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);
}

To manipuluje DOM tylko raz po zbudowaniu gigantycznego ciągu.

Christian Roman
źródło
można zoptymalizować to dalej i unikać korzystania z jQuery całkowicie zastępując $("#myselect").empty().append(opts);zgetElementById('myselect').innerHtml = opts;
vahanpwns
6

To, co zrobiłem z tablic dwuwymiarowych: Pierwsza kolumna to pozycja I, dodać do innerHTMLz <option>. Druga kolumna jest record_id i dodaj do valuez <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();
        }
    }
Słony
źródło
Wygląda dobrze. Szkoda, że ​​nie używa jQuery. Ponadto miałem wcześniej problemy z metodą select.options.add (). Nie mogę sobie przypomnieć, która przeglądarka i dokładny problem, ale postanowiłem odejść od tego i pozwolić jQuery zająć się różnicami.
Darryl Hein
jestem całkowitym noob z PHP i JQuerry, ale powyższy kod działa we wszystkich przeglądarkach. jedyny problem - nie działa dobrze na iPhonie, wysłałem pytanie na ten temat, do tej pory bez powodzenia :( stackoverflow.com/questions/11364040/…
Salty
5

Odkryłem, że jest to proste i działa świetnie.

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

Format JSON:

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

I kod jQuery wypełniający wartości do rozwijanego menu po sukcesie 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
źródło
3

Korzystając z funkcji $ .map (), możesz to zrobić w bardziej elegancki sposób:

$('#mySelect').html( $.map(selectValues, function(val, key){
    return '<option value="' + val + '">'+ key + '</option>';
}).join(''));
Dr Fred
źródło
Jest to trochę krótsze, ale jedynym problemem jest ucieczka od val i kluczowych zmienności, co robi zaakceptowana odpowiedź.
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
źródło
2

Ustaw swój identyfikator wyboru HTML w poniższej linii. Tutaj mySelectjest używany jako identyfikator elementu select.

   var options = $("#mySelect");

następnie pobierz obiekt, który jest selectValues ​​w tym scenariuszu i ustawia go na jquery dla każdej pętli. Użyje odpowiednio wartości i tekstu obiektów i dołącza je do wyboru opcji w następujący sposób.

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

Spowoduje to wyświetlenie tekstu jako listy opcji po wybraniu listy rozwijanej i po wybraniu tekstu zostanie użyta wartość wybranego tekstu.

Na przykład.

„1”: „test 1”, „2”: „test 2”,

Upuścić,

wyświetlana nazwa: test 1 -> wartość wynosi 1 wyświetlana nazwa: test 2 -> wartość wynosi 2

Dulith De Costa
źródło
proszę opisać trochę o rozwiązaniu.
Vinay Prajapati,
2

W rzeczywistości, aby uzyskać lepszą wydajność, lepiej jest zrobić listę opcji osobno i dołączyć, aby wybrać 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
źródło