I want only display one answer when I click on a question, but all answers are being shown.
let ques = document.querySelectorAll(".question")
let ans = document.querySelectorAll(".answer")
ques.forEach((question) => {
question.addEventListener("click", () => {
ans.forEach((answer) => {
answer.classList.toggle("display")
})
})
})
.answer {
display: none;
}
.answer.display {
display: block;
}
<div class="faq">
<div class="question">question</div>
<div class="answer">answer</div>
</div>
<div class="faq">
<div class="question">question</div>
<div class="answer">answer</div>
</div>
<div class="faq">
<div class="question">question</div>
<div class="answer">answer</div>
</div>
5
Answers
The issue in your code is because you’re looping through all the
.answer
elements, not the one related to the clicked.question
.To do what you need you can use
closest()
andquerySelector()
to find the.answer
within the same parent as the.question
which was clicked and toggle thedisplay
class on it. You can then loop through all other.answer
elements and remove thedisplay
class from them.Here’s a working example:
Shorter and with delegated event handling
Explanation: When someone clicks the body find out if a question was clicked, and if so get its next sibling (the answer) and toggle its display class.
Here’s a solution using an adjacent css sibling selector and event delegation. Now you only have to manipulate the
active
class on the.question
element to show the right answer.Delegate from the nearest static container – it is never useful to add an eventListener to many identical elements in the same container.
Use hidden for simplicity. Alternatively use
classList.toggle("display",tgt.nextElementSibling === answer)
Instead of attaching listeners to all the elements wrap the FAQ sections in a container, add one listener to that (this is known as event delegation), and catch events from its child elements as they "bubble up" the DOM.
If the element clicked on is a question you can toggle the display class on its
nextElementSibling
.You can cache the answer elements and then iterate over them with
forEach
in the handler.