Im making an accordion and wonder how to make an arrow (lets suppose its an arrow svg icon) rotate 180deg once an accordion element is clicked and expanded in Vanilla JS?
Currently it only rotates the first element from the dom found that is matching my selected tag, because of querySelector and not querySelectorAll. How to use querySelectorAll properly in this case so not all of them get rotated?
document.querySelectorAll("details").forEach((accordion) => {
accordion.addEventListener("click", () => {
document.querySelectorAll("details").forEach((event) => {
document.querySelector("details span").classList.add("active");
if (accordion !== event) {
event.removeAttribute("open");
}
});
});
});
summary{
list-style: none
}
details{
padding: 1rem;
background-color: lightblue;
}
details summary{
display: flex;
justify-content: space-between;
}
details:nth-child(even){
background-color: lightgreen;
}
p{
padding-top: 0.3rem;
}
.active{
transform: rotate(180deg);
}
span{
display: block;
}
<div>
<details>
<summary>
<h3>item1</h3>
<span>arrow</span> </summary>
<p>desc1</p>
</details>
<details>
<summary>
<h3>item2</h3>
<span>arrow</span>
</summary>
<p>desc2</p>
</details>
<details>
<summary>
<h3>item3</h3>
<span>arrow</span>
</summary>
<p>desc3</p>
</details>
</div>
>Solution :
Once your accordion is clicked you are running a loop through all the accordions and performing actions. But you only need to look at the span which is child of the clicked accordion.
You can use this. this inside eventlistener callbacks always give the element on which event is attached. (You cannot use arrow functions with this). That is why I have converted them to non arrow functions.
I am following the same logic as yours but after removing from all the accordions, I am modifying the properties of the children of the current accordion. Have a look:
document.querySelectorAll("details").forEach((accordion) => {
accordion.addEventListener("click", function () {
document.querySelectorAll("details").forEach(function (elem) {
elem.removeAttribute("open");
elem.querySelector("span").classList.remove("active");
}); this.querySelector("span").classList.add("active");
});
});
summary{
list-style: none
}
details{
padding: 1rem;
background-color: lightblue;
}
details summary{
display: flex;
justify-content: space-between;
}
details:nth-child(even){
background-color: lightgreen;
}
p{
padding-top: 0.3rem;
}
.active{
transform: rotate(180deg);
}
span{
display: block;
}
<div>
<details>
<summary>
<h3>item1</h3>
<span>arrow</span> </summary>
<p>desc1</p>
</details>
<details>
<summary>
<h3>item2</h3>
<span>arrow</span>
</summary>
<p>desc2</p>
</details>
<details>
<summary>
<h3>item3</h3>
<span>arrow</span>
</summary>
<p>desc3</p>
</details>
</div>