44

The code:

var newSelect=document.createElement('select');
index=0;
var optn = document.createElement("option");

//langArray is an array that contains different items..the size
//is not fixed for this array.

for(element in langArray)
{
   //Now i want to assign each item in langArray to each option tag
   //will it be sumthng like "optn.options[index]=new Option("Sports", "sportsvalue", true,  false);
   //optn.accept(langArray[0]);
   index++;
}

I'm trying to get options populated by this way but its not coming all right as I don't know how to populate the options from an array in JS. Do I even have to use the loop or can I just assign the langArray to some property of select element and every thing will be up and running?

MD. Mohiuddin Ahmed
  • 2,092
  • 2
  • 26
  • 35
samach
  • 3,244
  • 10
  • 42
  • 54
  • `for(element in langArray)` creates a global and is wide open for a bug, better to scope `element` to the block with `const element`. Top answer repeats this mistake. – ggorlen Aug 31 '22 at 18:30

6 Answers6

57

You can create the option inside the loop;

for(element in langArray)
{
   var opt = document.createElement("option");
   opt.value= index;
   opt.innerHTML = element; // whatever property it has

   // then append it to the select element
   newSelect.appendChild(opt);
   index++;
}

// then append the select to an element in the dom

2023 Update:

To make sure we avoid creating globals and remain in the correct scope, we can use map() and let.

let selectTag = document.createElement('select');
langArray.map( (lang, i) => {
    let opt = document.createElement("option");
    opt.value = i; // the index
    opt.innerHTML = lang;
    selectTag.append(opt);
});
Ibu
  • 42,752
  • 13
  • 76
  • 103
  • Doing opt.innerHTML did not work for me, but doing something like option.appendChild(document.createTextNode(langArray[i].text)); like in James Long's answer did. – Nick Apr 21 '22 at 03:37
  • i also think that @James Long's answer is more explicit . – Tarik Waleed Dec 15 '22 at 13:48
18

You need to create your option element inside your loop, set attributes and text and append it to the select element:

var select = document.createElement('select'),
    option,
    i = 0,
    il = langArray.length;

for (; i < il; i += 1) {
    option = document.createElement('option');
    option.setAttribute('value', langArray[i].value);
    option.appendChild(document.createTextNode(langArray[i].text));
    select.appendChild(option);
}

This assumes that your langArray looks something like this:

var langArray = [
    {value: "val1", text: "text 1"},
    {value: "val2", text: "text 2"}
];

You'll need to tweak the code to match your array

James Long
  • 4,629
  • 1
  • 20
  • 30
16

2021 answer is here:

const select_elem = document.createElement('select');
langArray.forEach(d=> select_elem.add(new Option(d.display,d.value)));
Cihan Yakar
  • 2,402
  • 28
  • 30
6
    var dynamicSelect = document.getElementById("selectID");

        langArray.forEach(function(item){ 
        {
                var newOption = document.createElement("option");
                newOption.text = item.toString();//item.whateverProperty

                dynamicSelect.add(newOption);

                //new select items should populated immediately
        });
MD. Mohiuddin Ahmed
  • 2,092
  • 2
  • 26
  • 35
6

As a more 'up-to-date' method based on @Ibu's (currently accepted and perfectly valid) answer, you can use the forEach method in JavaScript, like so:

let select_elem = document.createElement('select');

langArray.forEach((element, index) => {
  let option_elem = document.createElement('option');
  
  // Add index to option_elem
  option_elem.value = index;
  
  // Add element HTML
  option_elem.textContent = element;
  
  // Append option_elem to select_elem
  select_elem.appendChild(option_elem);
});

Using a forEach method tracks its own index, meaning you don't need to have to manually track your index (using something like var i=0; [...] i++) and is - I would argue - neater and more maintainable than a for loop. After all, you don't need to create any variables outside of the loop, or manually increment those variables, and - consequently - there is less chance of conflicts if the index variable (say, var i) is used elsewhere (e.g. if you have a loop within a loop).

It should be noted that this recommendation comes in a context - there will ultimately be contexts when a for loop is a best choice, and when a forEach loop will be a best choice. As I personally prioritise maintainability over speed, I would by default opt for a forEach loop. But that's not to say that it is the correct or only correct answer. Always, always, ALWAYS consider your personal use requirements over the advice of anyone on the Internet.

I have also swapped innerHTML for textContent. Ultimately the content within the option is always going to be text (you can't add HTML to an option) so using textContent is more descriptive to what you are ultimately going to be doing. And textContent is more performant than innerHTML as it does not parse the data being fed in. In fact, a benchmark shows that just changing innerHTML to textContent can improve performance by over x2.5.

As such this is likely to be more performant and more maintainable for those reading your code in the future. In this instance, unlike with a for loop, I can see no benefit to not using textContent over innerHTML.

Performance

One thing to note is that for-in loops are more performant than forEach loops. Though this is somewhat trivial (especially given the context), and in my opinion you should always prioritise maintainability over mere speed... unless performance is a vital criteria for what you are making (like, for example, if you are iterating over 1000s of values regularly and are experiencing bottlenecks). As the old saying goes though, "premature optimisation is the root of all evil".

Ultimately, maintainers of JS will work to increase the performance of most-used constructs, and the performance hit will in most cases be negligible and will probably decrease over time as devices get more powerful, and parsers are ever-more optimised.

The performance of an application that cannot be readily maintained, however, can be very high indeed. And will only ever go up, as poor maintainability precedes more bugs being introduced over time. Shaving 0.002ms off a loop now is not going to have any noticeable impact going forwards. A future developer trying to add a <strong> tag to an <option> element because they read, innerHTML = ... and assumed they could add HTML will have an impact going forwards.

Side note for older browsers

The forEach method works in all evergreen browsers, but not in IE11 or below. For this, you will need to either polyfill or use a service like Babel to compile the code into a pre-ES6 format.

You may also need to change the let keyword to var for older browsers too. The let keyword does work in IE11, though it has a number of issues. If you do not require support for older browsers though, using the keywords let and const are great habits to get into.

Community
  • 1
  • 1
Oliver
  • 2,930
  • 1
  • 20
  • 24
0

Another way to do this:

for (let i = 0; i < langArray.length; i++) {
    let opt = document.createElement("option");
    opt.value = langArray[i].id; //or i, depending on what you need to do
    opt.innerHTML = langArray[i].name; 
    $('#some-input').append(opt); //Chuck it into the dom here if you want
}
  1. For loop is often simpler to understand.
  2. Adding the option during the loop will avoid overwriting css styles that may be set at the "select" level of the HTML.
  3. Will be marginally slower.
Vincent Doba
  • 4,343
  • 3
  • 22
  • 42
HappyCoder
  • 5,985
  • 6
  • 42
  • 73
  • 3
    Why do you say that a `for` loop is simpler to understand than a `for-in` or `forEach` loop, and why is it marginally slower? And why are you using jQuery? – Oliver Sep 29 '19 at 20:18