user8121557
user8121557

Reputation: 181

How to dynamically add n select elements with options in HTML/JS

I'm trying to learn how to dynamically add n select elements with options to an HTML form using vanilla JS. There are a few related Stack Overflow questions but these focus on instances where you know how many select elements there will be 1 2. I don't know exactly how many select elements will need to be generated; I need to generate them dynamically. I started simpler by learning how to dynamically generate regular text fields:

for (let i = 0; i < res[0].length; i++) {
    container.appendChild(document.createTextNode(res[0][i])); 
    var input = document.createElement("input");
    input.type = res[1][i]; 
    input.name = res[0][i];
    input.classList.add("input");
    container.appendChild(input);
}

where

var res = [["textfield 1","text field 2"],["text","text"],[["none"],["none"]]];

That works fine for regular text fields so then I started working on select elements:

for (let i = 0; i < res[0].length; i++) {
      var select = document.getElementById("mySelect"); 
      var options = res[2][i];
      for(var j = 0; j < options.length; j++) {
          var optn = options[j];

          var elmnt = document.createElement("option");
          elmnt.name = res[0][i];
          elmnt.classList.add("input")
          elmnt.text = optn;
          elmnt.value = optn;
          select.id = res[0][i];
          select.add(elmnt);
                                            
                  }
}

where

var res = [["country","language"],["li","li"],[["Canada","Mexico","United States"],["English","Spanish","English"]]];

I thought that using select.id = res[0][i]; would accomplish what I want but I think that's just creating separate sets of options and not actually creating separate select elements. Right now, this yields the first select with countries but the second select for languages doesn't appear.

Here's the HTML:

<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  </head>
  <body>  

    <form name="myTest" id="myTest_frm">
      
    <div id="container"/>
    <select multiple = true id="mySelect">
    <option>Select an option</option>
    </select>
    
    </div>
  
    <br><input type="button" value="Submit" onClick="test()">
    </form>

I know that I can modify the HTML to include multiple select tags to make this work as shown below but that requires that I pre-know how many select elements I'll need. Again, I don't pre-know how many select elements there will be, i.e. res[0].length could be two as shown in the examples or it could be any other length.

Working but not dynamic:

<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  </head>
  <body>  

    <form name="myTest" id="myTest_frm">
      
    <div id="container"/>
    <select multiple = true id="mySelect">
    <option>Select an option</option>
    </select>

    <select multiple = true id="mySelect">
    <option>Select an option</option>
    </select>
    
    </div>
  
    <br><input type="button" value="Submit" onClick="test()">
    </form>

Upvotes: 0

Views: 1688

Answers (1)

vanowm
vanowm

Reputation: 10201

First you need establish the format of your dynamic data.

var res = [["country","language"],["li","li"],[["Canada","Mexico","United States"],["English","Spanish","English"]]]

This is a difficult to work with format, as it's "hard-coded" position of the list in the array (what's the li are for?)

For your purpose you probably should go with an object which contains list of options (array). This way, you can use object's key for select name:

var res = {
  country: ["Mexico" /*default*/, "Canada","Mexico","United States"],
  language: ["French" /*default*/, "English","Spanish","French"]
}

const container = document.getElementById("container");
for(let i in res)
{
  const select = document.createElement("select");
  select.value = res[i].shift(); //select default item, by removing first item from the array
  container.appendChild(select);

  for(let o = 0; o < res[i].length; o++)
  {
    const option = document.createElement("option");
    option.textContent = res[i][o];
    option.value = res[i][o];
    select.appendChild(option);
  };

}
<form name="myTest" id="myTest_frm">
  <div id="container"></div>
  <br><input type="button" value="Submit" onClick="test()">
</form>

Upvotes: 1

Related Questions