Search code examples
javascriptjsphtml-selectdisplay

Hide/Show <option> in select element when another option in another select is selected


I've been trying to achieve this using javascript but it doesn't seem to work, I have a JSTL based Select element in my JSP. Since I want to filter by "name" attribute those elements in the second Select that match with the ones in the first, So if I select "A" in first select, I want the options for the second select to be [A1,A2,A3...] and if I select "B" in the first select, I want the options for the second select to be [B1,B2,B3...] and so on.

That's why I use the "A" or "B" as name attribute on the second Select for every option that may match with the ones in the first Select.

My JSP snippet goes like this:

<tr>
<td align="right">address:</td>
<select id = "addressSelector" onchange = "filterBlocksByAddress()">
<option value="">
Choose an Address
</option>
<c:forEach items="${realStatesList}" var="realState">
<option>${realState.realStateID.address}</option>
</c:forEach>
</select>
<td><input type="text" name="address"></td>
</tr>
<tr>
<td align="right">block:</td>
<select id ="blockSelector">
<option value="">Choose a Block</option>
<c:forEach items="${realStatesList}" var="realState">
<option class = "hidden" name = "${realState.realStateID.address}">
${realState.realStateID.block}
</option>
</c:forEach>
</select>
<td><input type="text" name="block"></td>
</tr>

My Javascript method goes like this:

function filterBlocksByAddress() {
    let flag = true;
    let addressText = document.getElementById('addressSelector').options[document.getElementById('addressSelector').selectedIndex].text;
    let blockOptions = document.getElementsByName(addressText);
    for (i = 0; i < blockOptions.length; i++) {
        blockOptions[i].classList.add("hidden");
    }
    for (i = 0; i < blockOptions.length; i++) {
        if(blockOptions[i].getAttribute("name") == addressText) {
            blockOptions[i].classList.remove("hidden");
        }
    }
    return flag;
}

the hidden class is defined on css as .hidden{ display:none; } When the jsp loads the second select gets all its options hidden but as soon as I start to select Options in the first select, then second select starts to show the ones that matches (that's what I want), but the problem is that they never get hidden anymore when I change the selected option in the first select. Any Ideas?, Thanks a lot.


Solution

  • You can use document.querySelectorAll('#blockSelector option[name]').. to add hidden class to all your options and then remove hidden class from options where name="yourfirstselectvalue" .

    Demo Code :

    function filterBlocksByAddress(addressText) {
      console.log(addressText)
      //hide all options.
      document.querySelectorAll('#blockSelector option[name]').forEach(function(el) {
        el.classList.add("hidden")
      });
      //if not first one slected
      if (addressText != "Choose an Address") {
        //loop through options where values matches..
        document.querySelectorAll('#blockSelector option[name=' + addressText + ']').forEach(function(el) {
          el.classList.remove("hidden"); //remove class
        })
      }
      document.getElementById('blockSelector').selectedIndex = 0 //set first vlau slected
    
    }
    .hidden {
      display: none
    }
    <select id="addressSelector" onchange="filterBlocksByAddress(this.options[this.selectedIndex].text)">
      <option value="">Choose an Address</option>
      <option>A</option>
      <option>B</option>
    </select>
    <select id="blockSelector">
      <option value="">Choose a Block</option>
      <option class="hidden" name="A">
        A1
      </option>
      <option class="hidden" name="A">
        A2
      </option>
      <option class="hidden" name="B">
        B1
      </option>
      <option class="hidden" name="B">
        B2
      </option>
    
    </select>