0

I have this drop down that I compare with an array. If a value in the array matches the text of one of the options in the dropdown, then it is selected:

JS -Step One:

var topicArray = ['Apples', 'Tomatoes'];
populateExistingDropDowns ('topicSelect',topicArray);

Dropdown

<select class="topicSelect" multiple>
    <optgroup label="Crops">
        <option selected="" value=""></option>
        <option value="Apiculture">Apiculture</option>
        <option value="Apples">Apples</option>
        <option value="Aquaculture">Aquaculture</option>
        <option value="Blueberries">Blueberries</option>
    </optgroup>
    <optgroup label="Add Option" class="youOwn">
        <option value="own">Add Your Option</option>
    </optgroup>
</select>

JS - Step Two:

function populateExistingDropDowns(dd, array) {
    var select = document.getElementsByClassName(dd);
    for (var d = 0; d < array.length; d++) {
        for (var i = 0; i < select[0].options.length; i += 1) {
            if (select[0].options[i].text === array[d]) {
                select[0].options[i].selected = true;
            }
        }
    }
}

Here comes my issue: The the code showed above works just fine, but I would like to be able to add a new option if an option with the same array value doesn't exist. In the example shown above, there are two values ('Apple' and 'Tomatoes") values in the array. When I iterate through the array and the dropdown, the 'Apple' option is selected, but, how can I then add a new 'Tomatoes' options, and then select it also? Thanks in advance, please let me know if more details are needed.

Ronaldo Felipe
  • 402
  • 2
  • 13
cubanGuy
  • 1,226
  • 3
  • 26
  • 48

3 Answers3

2

I would like to be able to add a new option if an option with the same array value doesn't exist..

you can clone an option node modify it and append it to parent node,

in the snippet I added a dedicated function;

function populateExistingDropDowns(dd, array) {

  var select = document.getElementsByClassName(dd);
  outer:
  for (var d = 0; d < array.length; d++) {
    for (var i = 0; i < select[0].options.length; i += 1) {
      if (select[0].options[i].text === array[d]) {
        select[0].options[i].selected = true;
        continue outer;
      }
      //if you haven't matched and are in last loop
      if ( i === select[0].options.length - 1) {
        addOpt(array[d], select[0].options[i])  
      }
    }
  }
}


function addOpt(x,clone){
  var node = clone.cloneNode();
  node.selected= true;
  node.value= node.innerHTML= x;
  clone.parentNode.appendChild(node)
  
  
}
var topicArray = ['Apples', 'Tomatoes'];
populateExistingDropDowns ('topicSelect',topicArray);
<select class="topicSelect" multiple>
  <optgroup label="Crops">
    <option selected="" value=""></option>
    <option value="Apiculture">Apiculture</option>
    <option value="Apples">Apples</option>
    <option value="Aquaculture">Aquaculture</option>
    <option value="Blueberries">Blueberries</option>
  </optgroup>
  <optgroup label="Add Option" class="youOwn">
    <option value="own">Add Your Option</option>
  </optgroup>
</select>
maioman
  • 18,154
  • 4
  • 36
  • 42
1

One approach, using ES6 syntax is the following:

function populateExistingDropDowns(dd, array) {

  // using 'let' rather than 'var' to declare variables,
  // using document.querySelector(), rather than
  // getElementsByClassName(), because d.qS has support
  // in IE8 (whereas it does not support
  // getElementsByClassName()); however here we get the
  // first element that matches the selector:
  let dropdown = document.querySelector('.' + dd),

    // retrieving the collection of option elements,
    // HTMLSelectElement.options, and converting that
    // collection into an Array using Array.from():
    options = Array.from(dropdown.options);

  // iterating over each of the topics in the passed-in
  // array, using Array.prototype.forEach():
  array.forEach(function(topic) {

    // filtering the array of <option> elements to keep
    // only those whose text property is equal to the
    // current topic (from the array):
    let opts = options.filter(opt => topic === opt.text);

    // if the opts Array has a truthy non-zero length:
    if (opts.length) {

      // we iterate over the returned filtered Array
      // and, using Arrow function syntax, set each
      // node's selected property to true:
      opts.forEach(opt => opt.selected = true);
    } else {

      // otherwise, if the current topic returned no
      // <option> elements, we find the <optgroup>
      // holding the 'Crops' and append a new Child
      // using Node.appendChild(), and the new Option()
      // constructor to set the option-text, option-value
      // default-selected property and selected property:
      dropdown.querySelector('optgroup[label=Crops]')
        .appendChild(new Option(topic, topic, true, true));
    }
  });
}

var topicArray = ['Apples', 'Tomatoes'];
populateExistingDropDowns('topicSelect', topicArray);

function populateExistingDropDowns(dd, array) {
  let dropdown = document.querySelector('.' + dd),
    options = Array.from(dropdown.options);
  array.forEach(function(topic) {
    let opts = options.filter(opt => topic === opt.text);
    if (opts.length) {
      opts.forEach(opt => opt.selected = true);
    } else {
      dropdown.querySelector('optgroup[label=Crops]')
        .appendChild(new Option(topic, topic, true, true));
    }
  });
}

var topicArray = ['Apples', 'Tomatoes'];
populateExistingDropDowns('topicSelect', topicArray);
<select class="topicSelect" multiple>
  <optgroup label="Crops">
    <option value="Apiculture">Apiculture</option>
    <option value="Apples">Apples</option>
    <option value="Aquaculture">Aquaculture</option>
    <option value="Blueberries">Blueberries</option>
  </optgroup>
  <optgroup label="Add Option" class="youOwn">
    <option value="own">Add Your Option</option>
  </optgroup>
</select>

JS Fiddle demo.

To recompose the above, using ES5:

function populateExistingDropDowns(dd, array) {

  // using 'var' to declare variables:
  var dropdown = document.querySelector('.' + dd),

    // using Array.prototype.slice(), with
    // Function.prototype.call(), to convert the collection
    // of <option> element-nodes into an Array:
    options = Array.prototype.slice.call(dropdown.options, 0);

  array.forEach(function(topic) {

    // using the anonymous functions available to the
    // Array methods, rather than Arrow functions,
    // but doing exactly the same as the above:
    var opts = options.filter(function(opt) {
      return topic === opt.text
    });
    if (opts.length) {
      opts.forEach(function(opt) {
        opt.selected = true;
      });
    } else {
      dropdown.querySelector('optgroup[label=Crops]')
        .appendChild(new Option(topic, topic, true, true));
    }
  });
}

var topicArray = ['Apples', 'Tomatoes'];
populateExistingDropDowns('topicSelect', topicArray);

function populateExistingDropDowns(dd, array) {

  var dropdown = document.querySelector('.' + dd),
    options = Array.prototype.slice.call(dropdown.options, 0);

  array.forEach(function(topic) {
    var opts = options.filter(function(opt) {
      return topic === opt.text
    });
    if (opts.length) {
      opts.forEach(function(opt) {
        opt.selected = true;
      });
    } else {
      dropdown.querySelector('optgroup[label=Crops]')
        .appendChild(new Option(topic, topic, true, true));
    }
  });
}

var topicArray = ['Apples', 'Tomatoes'];
populateExistingDropDowns('topicSelect', topicArray);
<select class="topicSelect" multiple>
  <optgroup label="Crops">
    <option value="Apiculture">Apiculture</option>
    <option value="Apples">Apples</option>
    <option value="Aquaculture">Aquaculture</option>
    <option value="Blueberries">Blueberries</option>
  </optgroup>
  <optgroup label="Add Option" class="youOwn">
    <option value="own">Add Your Option</option>
  </optgroup>
</select>

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
0

Thank you all that responded to my question. I ended up using this instead:

function populateExistingDropDowns(dd, array) {
var select = document.getElementsByClassName(dd);
var opt = document.createElement('option');
 for (var d = 0; d < array.length; d++) {
  for (var q = 0; q < select[0].length; q++) {
   if (select[0].options[q].text !== array[d]) {
    opt.value = array[d];
    opt.text = array[d];
    select[0].children[1].appendChild(opt);
    opt.selected = true;
     } else {
    select[0].options[q].selected = true;
           }
      }
     }
   }

Fiddle

cubanGuy
  • 1,226
  • 3
  • 26
  • 48