20

My requirement is that for a selection in a 'meal' drop down list, a second drop down list 'category' should get dynamically populated with values related to the selection in first drop down list. Then depending on what is selected in the meal dropdown, the list should change in category. I have written the following Javascript function but the output I'm getting is not freshly populating the 2nd dropdown. On change of a selection, the new list is just getting appended to the old list.

function changecat() {
    var selectHTML = "";

    var A = ["Soup", "Juice", "Tea", "Others"];
    var B = ["Soup", "Juice", "Water", "Others"];
    var C = ["Soup", "Juice", "Coffee", "Tea", "Others"];

    if (document.getElementById("meal").value == "A") {
        var select = document.getElementById('category').options.length;

        for (var i = 0; i < select; i++) {
            document.getElementById('category').options.remove(i);
        }

        for (var i = 0; i < A.length; i++) {
            var newSelect = document.createElement('option');
            selectHTML = "<option value='" + A[i] + "'>" + A[i] + "</option>";
            newSelect.innerHTML = selectHTML;
            document.getElementById('category').add(newSelect);
        }
    }

    else if (document.getElementById("meal").value == "B") {
        var select = document.getElementById('category').options.length;

        for (var i = 0; i < select; i++) {
            document.getElementById('category').options.remove(i);
        }

        for (var i = 0; i < B.length; i++) {
            var newSelect = document.createElement('option');
            selectHTML = "<option value='" + B[i] + "'>" + B[i] + "</option>";
            newSelect.innerHTML = selectHTML;
            document.getElementById('category').add(newSelect);
        }
    }

    else if (document.getElementById("project").value == "C") {
        var select = document.getElementById('category').options.length;

        for (var i = 0; i < select; i++) {
            document.getElementById('category').options.remove(i);
        }

        for (var i = 0; i < C.length; i++) { 
            var newSelect = document.createElement('option');
            selectHTML = "<option value='" + C[i] + "'>" + C[i] + "</option>";
            newSelect.innerHTML = selectHTML;
            document.getElementById('category').add(newSelect);
        }
    }
}

HTML-  
<select name="meal" id="meal" onchange="changecat();">
    <option value="">Select</option>
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
</select>

<select name="category" id="category">
    <option value="">Select</option>
</select>
erickb
  • 6,193
  • 4
  • 24
  • 19
Zim
  • 261
  • 1
  • 3
  • 9
  • possible duplicate of [How do I clear all options in a dropdown box?](http://stackoverflow.com/questions/3364493/how-do-i-clear-all-options-in-a-dropdown-box) – glend May 14 '15 at 07:56
  • Take a look at my EDIT, you just need to use a switch statement. – cнŝdk May 14 '15 at 09:42

3 Answers3

25

Hope this might help you.

JSFiddle : DEMO

HTML

<select name="meal" id="meal" onChange="changecat(this.value);">
    <option value="" disabled selected>Select</option>
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
</select>
<select name="category" id="category">
    <option value="" disabled selected>Select</option>
</select>

JS

var mealsByCategory = {
    A: ["Soup", "Juice", "Tea", "Others"],
    B: ["Soup", "Juice", "Water", "Others"],
    C: ["Soup", "Juice", "Coffee", "Tea", "Others"]
}

    function changecat(value) {
        if (value.length == 0) document.getElementById("category").innerHTML = "<option></option>";
        else {
            var catOptions = "";
            for (categoryId in mealsByCategory[value]) {
                catOptions += "<option>" + mealsByCategory[value][categoryId] + "</option>";
            }
            document.getElementById("category").innerHTML = catOptions;
        }
    }

There is a loop (for...in loop) in JavaScript, which would help you in this case

A for...in loop only iterates over enumerable properties. Objects created from built–in constructors like Array and Object have inherited non–enumerable properties from Object.prototype and String.prototype, such as String's indexOf() method or Object's toString() method. The loop will iterate over all enumerable properties of the object itself and those the object inherits from its constructor's prototype (properties closer to the object in the prototype chain override prototypes' properties).

In each iteration one property from object is assigned to variable-name and this loop continues till all the properties of the object are exhausted.

For more Link

divy3993
  • 5,732
  • 2
  • 28
  • 41
  • Thanks divy3993! That worked. But not sure I understood how it is working, especially the categoryId in 'for' loop part. Could you explain the flow? – Zim May 14 '15 at 09:20
  • Why whould you put the objects in another one? – cнŝdk May 14 '15 at 10:10
  • There is never, ever a reason to duplicate the option's text as its `value` value. If the two values are identical, never bloat your markup by declaring `value`. – mickmackusa Feb 18 '21 at 23:46
1

You can use onchange event and use a switch statement with the selected value from the first dropdown and according to it append the options to the second list:

    var A= ["Soup", "Juice", "Tea","Others"];
    var B= ["Soup","Juice","Water", "Others"];
    var C= ["Soup","Juice","Coffee", "Tea","Others"];

var changeCat = function changeCat(firstList) {
    var newSel = document.getElementById("category");
    //if you want to remove this default option use newSel.innerHTML=""
    newSel.innerHTML="<option value=\"\">Select</option>"; // to reset the second list everytime
    var opt;

      //test according to the selected value
      switch (firstList.options[firstList.selectedIndex].value) {
          case "A":
              for (var i=0; len=A.length, i<len; i++) {
                    opt = document.createElement("option");
                    opt.value = A[i];
                    opt.text = A[i];
                    newSel.appendChild(opt);
              }
              break;
          case "B":
              for (var i=0; len=B.length, i<len; i++) {
                    opt = document.createElement("option");
                    opt.value = B[i];
                    opt.text = B[i];
                    newSel.appendChild(opt);
              }
              break;
          case "C":
              for (var i=0; len=C.length, i<len; i++) {
                    opt = document.createElement("option");
                    opt.value = C[i];
                    opt.text = C[i];
                    newSel.appendChild(opt);
              }
              break;
      }

}
<select name="meal" id="meal" onchange="changeCat(this);">
     <option value="">Select</option>
     <option value="A">A</option>
     <option value="B">B</option>
     <option value="C">C</option>
</select>

<select name="category" id="category" size="5">
     <option value="">Select</option>
</select>

I used size="5" with the second dropdown to see the live result changes for each selection.

cнŝdk
  • 31,391
  • 7
  • 56
  • 78
1

The reason why your code gets appended is because in the for loop for clearing the second drop down list, the update expression is not required as the list is itself being reduced in size and so in every iteration the length of the list decreases, and so you are unable to clear the whole list. Also the removal function should be outside the if conditions to avoid redundancy.`function changecat() { var selectHTML = "";

var A = ["Soup", "Juice", "Tea", "Others"];
var B = ["Soup", "Juice", "Water", "Others"];
var C = ["Soup", "Juice", "Coffee", "Tea", "Others"];
var select = document.getElementById('category').options.length;

    for (var i = 0; i < select; ) {
        document.getElementById('category').options.remove(i);
    }

if (document.getElementById("meal").value == "A") {


    for (var i = 0; i < A.length; i++) {
        var newSelect = document.createElement('option');
        selectHTML = "<option value='" + A[i] + "'>" + A[i] + "</option>";
        newSelect.innerHTML = selectHTML;
        document.getElementById('category').add(newSelect);
    }
}

else if (document.getElementById("meal").value == "B") {

    for (var i = 0; i < B.length; i++) {
        var newSelect = document.createElement('option');
        selectHTML = "<option value='" + B[i] + "'>" + B[i] + "</option>";
        newSelect.innerHTML = selectHTML;
        document.getElementById('category').add(newSelect);
    }
}

else if (document.getElementById("project").value == "C") {

    for (var i = 0; i < C.length; i++) { 
        var newSelect = document.createElement('option');
        selectHTML = "<option value='" + C[i] + "'>" + C[i] + "</option>";
        newSelect.innerHTML = selectHTML;
        document.getElementById('category').add(newSelect);
    }
}

}