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

Time:10-16

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 >
          <div >
            <p >
              Lorem ipsum dolor sit amet consectetur.
              <i ></i>
              <i ></i>
            </p>

            <p >
              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 >
            <p >
              Lorem ipsum dolor sit amet consectetur.
              <i ></i>
              <i ></i>
            </p>

            <p >
              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 >
            <p >
              Lorem ipsum dolor sit amet consectetur.
              <i ></i>
              <i ></i>
            </p>

            <p >
              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 >
            <p >
              Lorem ipsum dolor sit amet consectetur.
              <i ></i>
              <i ></i>
            </p>

            <p >
              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 >
            <p >
              Lorem ipsum dolor sit amet consectetur.
              <i ></i>
              <i ></i>
            </p>

            <p >
              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

.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?

CodePudding user response:

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 >
  <div >
    <p >
      Lorem ipsum dolor sit amet consectetur.
      <i ></i>
      <i ></i>
    </p>

    <p >
      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 >
    <p >
      Lorem ipsum dolor sit amet consectetur.
      <i ></i>
      <i ></i>
    </p>

    <p >
      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 >
    <p >
      Lorem ipsum dolor sit amet consectetur.
      <i ></i>
      <i ></i>
    </p>

    <p >
      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 >
    <p >
      Lorem ipsum dolor sit amet consectetur.
      <i ></i>
      <i ></i>
    </p>

    <p >
      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 >
    <p >
      Lorem ipsum dolor sit amet consectetur.
      <i ></i>
      <i ></i>
    </p>

    <p >
      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>

  • Related