-1

I have a footer with several dropdown items. I want to toggle the "active" classList specifically for the element that was clicked. So far my code is:

I have multiple containers like this:

let dropDowns = document.querySelectorAll('.footer-arrow-container')
let dropDownList = document.querySelector('.footer-items-list')

dropDowns.forEach((dropDown) => {
  dropDown.addEventListener('click', () => {
    dropDownList.closest('ul').classList.toggle('active')
  })
})
.footer-items-list {
  display: none;
}

.active {
  display: flex;
}
    <div class="footer-item-container">
      <div class="footer-arrow-container">
        <!-- dropDowns ; querySelectorAll -->
        <h2 class="footer-item-title">
          Test
        </h2>
        <img/>
      </div>
      <div class="footer-dropdown-list-container">
        <ul class="footer-items-list">
          <!-- dropDownList : querySelector -->
          <li>List item 1</li>
          <li>List item 2</li>
        </ul>
      </div>
    </div>

<div class="footer-item-container">
      <div class="footer-arrow-container">
        <!-- dropDowns ; querySelectorAll -->
        <h2 class="footer-item-title">
          Test
        </h2>
        <img/>
      </div>
      <div class="footer-dropdown-list-container">
        <ul class="footer-items-list">
          <!-- dropDownList : querySelector -->
          <li>List item 1</li>
          <li>List item 2</li>
        </ul>
      </div>
    </div>

Currently, this is only selecting the "ul" from the first list. It doesn't work for the other lists individually so I'm clearly selecting it incorrectly in the JavaScript and I'm not sure the best way to do this.

Gabriel
  • 41
  • 7
  • Because then ALL the .footer-items-lists will be activated regardless of which footer-arrow-container you click on. I only need the one that is clicked to activate – Gabriel Sep 23 '22 at 17:30
  • You want to use `dropdown.querySelector('.footer-items-list').classList.toggle('active')` – Heretic Monkey Sep 23 '22 at 17:34
  • Uncaught TypeError: Cannot read properties of null (reading 'classList') – Gabriel Sep 23 '22 at 17:36
  • I read your post incorrectly. Your HTML structure is ... unfortunate. You want to use `dropdown.querySelector('+.footer-dropdown-list-container').querySelector('.footer-items-list').classList.toggle('active')` – Heretic Monkey Sep 23 '22 at 17:38
  • dropDown.addEventListener('click', (e.target) => { e.target.closest('ul').classList.toggle('active') }) – epascarello Sep 23 '22 at 17:42

1 Answers1

0

The HTML structure is unclear. I've taken you at your word, that each footer item has the same structure, and placed two in this example. Basically, the code goes up to the common ancestor, then down to the child.

let dropDowns = document.querySelectorAll('.footer-arrow-container')

dropDowns.forEach((dropDown) => {
  dropDown.addEventListener('click', () => {
    dropDown.closest('.footer-item-container').querySelector('.footer-items-list').classList.toggle('active')
  })
})
.footer-items-list {
  display: none;
}

.active {
  display: flex;
}
<div class="footer-item-container">
  <div class="footer-arrow-container">
    <!-- dropDowns ; querySelectorAll -->
    <h2 class="footer-item-title">
      Test
    </h2>
    <img/>
  </div>
  <div class="footer-dropdown-list-container">
    <ul class="footer-items-list">
      <!-- dropDownList : querySelector -->
      <li>List item 1</li>
      <li>List item 2</li>
    </ul>
  </div>
</div>
<div class="footer-item-container">
  <div class="footer-arrow-container">
    <!-- dropDowns ; querySelectorAll -->
    <h2 class="footer-item-title">
      Test 2
    </h2>
    <img/>
  </div>
  <div class="footer-dropdown-list-container">
    <ul class="footer-items-list">
      <!-- dropDownList : querySelector -->
      <li>List item 3</li>
      <li>List item 4</li>
    </ul>
  </div>
</div>
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • Yep! That's it. I can get rid of " – Gabriel Sep 23 '22 at 17:49
  • Why use `addEventListener` when you have `onclick` ? – Mister Jojo Sep 23 '22 at 18:04
  • What would be a clearer way to structure this HTML after footer-dropdown-list-container is removed? – Gabriel Sep 23 '22 at 18:54
  • @MisterJojo `onclick` is a property mirroring the legacy HTML attribute of the same name. It has many limitations, including the inability to add more than one event listener. `addEventListener` is a modern approach, separating the event listener from the HTML attributes, and allowing consumers to attach to either the bubbling or capturing phase, provide extra data to event objects, allowing for custom events, etc. See, e.g., [addEventListener vs onclick](https://stackoverflow.com/q/6348494/215552) for more. – Heretic Monkey Sep 23 '22 at 19:02
  • I would say locating the list of items associated with a particular footer item within the same element would make it clearer (e.g., all within `.footer-arrow-container`). By "unclear" I meant in the question; since there was only one footer element, it was unclear whether `.footer-item-container` contained a number of pairs of `.footer-arrow-container` and `footer-dropdown-list-container`, or if there were multiple `.footer-item-container`s. I guessed correctly, luckily. There's nothing inherently wrong with the structure you've chosen; it's just a lot of HTML. – Heretic Monkey Sep 23 '22 at 19:08
  • Thank you for the input! I tried removing as much code as possible in the question to make it seem simpler, but I ended up making it more confusing! – Gabriel Sep 23 '22 at 19:22
  • I'd rollback the changes you made to the question; you made it look like I answered a different question! Keep the same structure as you had; maybe just add the second footer item so it's clear what repeats. In your real code, maybe simplifying the structure would help make it easier to code. – Heretic Monkey Sep 23 '22 at 19:31
  • Ok, edited it in back again – Gabriel Sep 23 '22 at 19:41
  • tell me something that I don't know. For example why in the present case would this object method be insufficient? – Mister Jojo Sep 23 '22 at 21:02