Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a reason why classlist.add is not adding the "hide" class

I’m trying to create an accordion component, the angle-up element is meant to close the section when you click it but it’s not adding the hide class, what’s the problem?

The html (icons are from font-awesome)

<div class="accordion-items">
          <div class="accordion-item">
            <p class="item-header">
              Lorem ipsum dolor sit amet consectetur.
              <i class="angle-down fa fa-angle-down"></i>
              <i class="fa fa-angle-up angle-up hide"></i>
            </p>

            <p class="item-content hide">
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
              quos eum cupiditate nulla quas ea numquam praesentium, molestias
              culpa nemo ab fuga deserunt.
            </p>
            <!-- <hr /> -->
          </div>

          <div class="accordion-item">
            <p class="item-header">
              Lorem ipsum dolor sit amet consectetur.
              <i class="angle-down fa fa-angle-down"></i>
              <i class="fa fa-angle-up angle-up hide"></i>
            </p>

            <p class="item-content hide">
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
              quos eum cupiditate nulla quas ea numquam praesentium, molestias
              culpa nemo ab fuga deserunt.
            </p>
            <!-- <hr /> -->
          </div>

          <div class="accordion-item">
            <p class="item-header">
              Lorem ipsum dolor sit amet consectetur.
              <i class="angle-down fa fa-angle-down"></i>
              <i class="fa fa-angle-up angle-up hide"></i>
            </p>

            <p class="item-content hide">
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
              quos eum cupiditate nulla quas ea numquam praesentium, molestias
              culpa nemo ab fuga deserunt.
            </p>
            <!-- <hr /> -->
          </div>

          <div class="accordion-item">
            <p class="item-header">
              Lorem ipsum dolor sit amet consectetur.
              <i class="angle-down fa fa-angle-down"></i>
              <i class="fa fa-angle-up angle-up hide"></i>
            </p>

            <p class="item-content hide">
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor
              quos eum cupiditate nulla quas ea numquam praesentium, molestias
              culpa nemo ab fuga deserunt.
            </p>
            <!-- <hr /> -->
          </div>

          <div class="accordion-item">
            <p class="item-header">
              Lorem ipsum dolor sit amet consectetur.
              <i class="fa fa-angle-down angle-down"></i>
              <i class="fa fa-angle-up angle-up hide"></i>
            </p>

            <p class="item-content hide">
              Lorem ipsum dolor sit amet consectetur adipisicing elit. Hic quasi
              nam dolorem aliquam, placeat, sed dolores provident natus,
              voluptate rem vel numquam. Repellendus.
            </p>
            <!-- <hr /> -->
          </div>
        </div>

The css

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

.hide {
  display: none;
}

.bold {
  font-weight: 700;
}

p {
  padding: 0.5em;
}

.accordion-item {
  border-bottom: 1px solid gray;
}

Javascript

"use strict"

const itemHeaderEls = document.querySelectorAll(".item-header")
const itemContentEls = document.querySelectorAll(".item-content")
const angleDownEls = document.querySelectorAll(".angle-down")
const angleUpEls = document.querySelectorAll(".angle-up")

const openItemContent = (i) => {
  itemHeaderEls[i].classList.add("bold")
  itemContentEls[i].classList.remove("hide")
  angleUpEls[i].classList.remove("hide")
  angleDownEls[i].classList.add("hide")
}

const closeItemContent = (i) => {
  itemHeaderEls[i].classList.remove("bold")
  itemContentEls[i].classList.add("hide")
  angleUpEls[i].classList.add("hide")
  angleDownEls[i].classList.remove("hide")
}

itemHeaderEls.forEach((el) => {
  el.addEventListener("click", () => {
    const itemIndex = Array.from(itemHeaderEls).indexOf(el)
    openItemContent(itemIndex)
  })
})

angleUpEls.forEach((el) => {
  el.addEventListener("click", () => {
    const itemIndex = Array.from(angleUpEls).indexOf(el)
    closeItemContent(itemIndex)
  })
})

angleDownEls.forEach((el) => {
  el.addEventListener("click", () => {
    const testIndex = Array.from(angleDownEls).indexOf(el)
    openItemContent(testIndex)
  })
})

When I click the icon i’d like to add the hide class and remove the bold class, why won’t it work?

>Solution :

As per my comment, the issue is because when you click on the .angle-up or .angle-down elements, the click event is bubbling up to the parent and it causes both the close + open function to be fired at the same time.

The trick is simply to use e.stopPropagation() on the click event handlers bound to the child nodes.

See example below:

const itemHeaderEls = document.querySelectorAll(".item-header")
const itemContentEls = document.querySelectorAll(".item-content")
const angleDownEls = document.querySelectorAll(".angle-down")
const angleUpEls = document.querySelectorAll(".angle-up")

const openItemContent = (i) => {
  itemHeaderEls[i].classList.add("bold")
  itemContentEls[i].classList.remove("hide")
  angleUpEls[i].classList.remove("hide")
  angleDownEls[i].classList.add("hide")
}

const closeItemContent = (i) => {
  itemHeaderEls[i].classList.remove("bold")
  itemContentEls[i].classList.add("hide")
  angleUpEls[i].classList.add("hide")
  angleDownEls[i].classList.remove("hide")
}

itemHeaderEls.forEach((el) => {
  el.addEventListener("click", () => {
    const itemIndex = Array.from(itemHeaderEls).indexOf(el)
    openItemContent(itemIndex)
  })
})

angleUpEls.forEach((el) => {
  el.addEventListener("click", (e) => {
    e.stopPropagation();
    const itemIndex = Array.from(angleUpEls).indexOf(el)
    closeItemContent(itemIndex)
  })
})

angleDownEls.forEach((el) => {
  el.addEventListener("click", (e) => {
    e.stopPropagation();
    const testIndex = Array.from(angleDownEls).indexOf(el)
    openItemContent(testIndex)
  })
})
.hide {
  display: none !important;
}

.bold {
  font-weight: 700;
}

p {
  padding: 0.5em;
}

.accordion-item {
  border-bottom: 1px solid gray;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" rel="stylesheet" />
<div class="accordion-items">
  <div class="accordion-item">
    <p class="item-header">
      Lorem ipsum dolor sit amet consectetur.
      <i class="angle-down fa fa-angle-down"></i>
      <i class="fa fa-angle-up angle-up hide"></i>
    </p>

    <p class="item-content hide">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor quos eum cupiditate nulla quas ea numquam praesentium, molestias culpa nemo ab fuga deserunt.
    </p>
  </div>

  <div class="accordion-item">
    <p class="item-header">
      Lorem ipsum dolor sit amet consectetur.
      <i class="angle-down fa fa-angle-down"></i>
      <i class="fa fa-angle-up angle-up hide"></i>
    </p>

    <p class="item-content hide">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor quos eum cupiditate nulla quas ea numquam praesentium, molestias culpa nemo ab fuga deserunt.
    </p>
  </div>

  <div class="accordion-item">
    <p class="item-header">
      Lorem ipsum dolor sit amet consectetur.
      <i class="angle-down fa fa-angle-down"></i>
      <i class="fa fa-angle-up angle-up hide"></i>
    </p>

    <p class="item-content hide">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor quos eum cupiditate nulla quas ea numquam praesentium, molestias culpa nemo ab fuga deserunt.
    </p>
  </div>

  <div class="accordion-item">
    <p class="item-header">
      Lorem ipsum dolor sit amet consectetur.
      <i class="angle-down fa fa-angle-down"></i>
      <i class="fa fa-angle-up angle-up hide"></i>
    </p>

    <p class="item-content hide">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor quos eum cupiditate nulla quas ea numquam praesentium, molestias culpa nemo ab fuga deserunt.
    </p>
  </div>

  <div class="accordion-item">
    <p class="item-header">
      Lorem ipsum dolor sit amet consectetur.
      <i class="fa fa-angle-down angle-down"></i>
      <i class="fa fa-angle-up angle-up hide"></i>
    </p>

    <p class="item-content hide">
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Hic quasi nam dolorem aliquam, placeat, sed dolores provident natus, voluptate rem vel numquam. Repellendus.
    </p>
  </div>
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading