NightmaresCoding
NightmaresCoding

Reputation: 131

Close dropdown on click

const dropdownBtns = document.querySelectorAll('.dropdown-btn');
const dropdownLists = document.querySelectorAll('.dropdown-list');

dropdownBtns.forEach(function(dropdownBtn) {
  dropdownBtn.addEventListener('click', function() {
    dropdownLists.forEach(function(dropdownList) {
      if (dropdownList !== this.nextElementSibling) {
        dropdownList.style.display = 'none';
      }
    });
    this.nextElementSibling.style.display = this.nextElementSibling.style.display === 'block' ? 'none' : 'block';
    
  });
});
.container {
  display: flex;
  gap: 50px;
}

.dropdown-list {
  display: none;
}
<div class="container">
  
  <div class="dropdown">
    <button class="dropdown-btn">Dropdown 1</button>
    <ul class="dropdown-list">
      <li><input type="checkbox" id="item-1"> <label for="item-1">Item 1</label></li>
      <li><input type="checkbox" id="item-2"> <label for="item-2">Item 2</label></li>
      <li><input type="checkbox" id="item-3"> <label for="item-3">Item 3</label></li>
    </ul>
  </div>
  <div class="dropdown">
    <button class="dropdown-btn">Dropdown 2</button>
    <ul class="dropdown-list">
      <li><input type="checkbox" id="item-4"> <label for="item-4">Item 4</label></li>
      <li><input type="checkbox" id="item-5"> <label for="item-5">Item 5</label></li>
      <li><input type="checkbox" id="item-6"> <label for="item-6">Item 6</label></li>
    </ul>
  </div>
 
</div>

Having a list of dropdowns I'd like to close other dropdown list if one is clicked and close itself if its already open. First part is working however button isn't closing the currently open dropdown list.

Upvotes: 2

Views: 75

Answers (1)

Roko C. Buljan
Roko C. Buljan

Reputation: 206028

Target instead your parent .dropdown wrappers, toggle a class like is-active, style in CSS accordingly.

  • Use Element.classList and the respective .toggle() and .remove() prototype methods:

const elsDD = document.querySelectorAll('.dropdown')

elsDD.forEach(elDD => {
  elDD.querySelector(".dropdown-btn").addEventListener("click", () => {
    elsDD.forEach(el => {
      el.classList[el === elDD ? "toggle" : "remove"]("is-active");
    });
  }); 
});
.container {
  display: flex;
  gap: 50px;
}

.dropdown .dropdown-list {
  display: none;
}

.dropdown.is-active .dropdown-list {
  display: initial;
}
<div class="container">

  <div class="dropdown">
    <button class="dropdown-btn">Dropdown 1</button>
    <ul class="dropdown-list">
      <li><label><input type="checkbox" name="c1" value="1">Item 1</label></li>
      <li><label><input type="checkbox" name="c1" value="2">Item 2</label></li>
      <li><label><input type="checkbox" name="c1" value="3">Item 3</label></li>
    </ul>
  </div>
  
  <div class="dropdown">
    <button class="dropdown-btn">Dropdown 2</button>
    <ul class="dropdown-list">
      <li><label><input type="checkbox" name="c2" value="4"> Item 4</label></li>
      <li><label><input type="checkbox" name="c2" value="5"> Item 5</label></li>
      <li><label><input type="checkbox" name="c2" value="6"> Item 6</label></li>
    </ul>
  </div>

</div>

The above solution is pretty slick since you can style as "active" not only the .dropdown wrapper, but also any child element by just descending from the parent: .dropdown.is-active .dropdown-btn { background: gold; }. You get the point.

Upvotes: 1

Related Questions