I am trying to create a piece of javascript code that will only hide and show each form on the page that corresponds with its id property. So imagine having 4 buttons visible on the page and the form elements are hidden by default, once a single button with its matching id to the form is clicked it will only toggle that form. Here is the code i have tried
function _(x) {
return document.getElementById(x);
}
const catBtn = _("catBtn");
const blogBtn = _("blogBtn");
const videoBtn = _("VideoBtn");
const prodBtn = _("prodBtn");
const catForm = _("catForm");
const blogForm = _("blogForm");
const videoForm = _("VideoForm");
const prodForm = _("prodForm");
document.addEventListener('click', function(e) {
if (e.target.id === catBtn) {
// catForm.classList.toggle("showHide");
console.log("you clicked the cat btn");
} else if (e.target.id === blogBtn) {
// blogForm.classList.toggle("showHide");
console.log("you clicked the blog btn");
} else if (e.target.id === videoBtn) {
// videoForm.classList.toggle("showHide");
console.log("you clicked the video btn");
} else if (e.target.id === prodForm) {
// prodForm.classList.toggle("showHide");
console.log("you clicked the product btn");
}
})
<div class="new__btn">
<button id="catBtn">New Category</button>
</div>
<div class="new__btn">
<button id="blogBtn">New Blog</button>
</div>
<div class="new__btn">
<button id="videoBtn">New Video</button>
</div>
<div class="new__btn">
<button id="prodBtn">New Product</button>
</div>
<div id="catForm">
Hide or show this div for the categories
<div class="panel">
<div class="panel__head">Panel Head</div>
<div class="panel__body">Panel Body</div>
<div class="panel__footer">Panel Footer</div>
</div>
</div>
<div id="blogForm">
Hide or show this div for the blogs
<div class="panel">
<div class="panel__head">Panel Head</div>
<div class="panel__body">Panel Body</div>
<div class="panel__footer">Panel Footer</div>
</div>
</div>
<div>
<div id="videoForm">
Hide or show this div for the videos
<div class="panel">
<div class="panel__head">Panel Head</div>
<div class="panel__body">Panel Body</div>
<div class="panel__footer">Panel Footer</div>
</div>
</div>
<div id="prodForm">
Hide or show this div for the products
<div class="panel">
<div class="panel__head">Panel Head</div>
<div class="panel__body">Panel Body</div>
<div class="panel__footer">Panel Footer</div>
</div>
</div>
5
Answers
First of all you are comparing Nodes, with strings (
e.target.id
returns astring
) which will always return false.Second, you are applying an event listener to document, meaning you are adding an eventListener to the entire document, wherever you click it will trigger.
You need to add an eventListener to every button. You can do something like this:
You can also do a
document.querySelectAll('button')
and loop over the element, apply the event listener above.Hope this helps!
The previous answer covered one option to solve this problem, but the clicks could also be detected in the way you were using earlier, by attaching and event listener to the document. All you need to do is replace
e.target.id
with juste.target
because the code should be comparing an element to an element instead of an id to an element.I would take an entirely different approach with this problem. What I suggest is tagging your buttons and forms using data attribues and then dynamically showing and hiding the forms based on what button was clicked. This will allow you to easily add new forms.
Here is an implementation of my approach that uses querySelectory and data attributes. If you have any questions please feel free to ask away and I’ll do my best to elaborate on my solution for you.
If you wrap your buttons and forms in containing elements, and add data attributes to both the buttons and forms you can use event delegation. This allows you to attach one listener to the buttons container which will catch events from its child elements as they "bubble up" the DOM.
The handler can then check that it was a button that was clicked, extract its data id (which will correspond to an identical data id on a form), and use that id in a selector to target that form.
Then it’s just a matter of using CSS to toggle the "show" class.
As you can see from the example you can use the same method to toggle an active class to the clicked button too.
Additional documenation
querySelector
/ –querySelectorAll
Destructuring assignment
Template/string literals
matches
Data attributes
Event.target
ok i solved it, with a little research and fine tuning i was able to use this to make everything work as i needed it. So in case anyone else faces this issue here is the code i used