4

I have a checkbox inside a label. I added the event listener for the click event to the label, so as to trigger the class.

It does work when I click the checkbox.

However, if I click the label, nothing changes. Why is that, considering that the event is binded to the label and not the checkbox?

const formCheck = document.querySelector('.drinos-checker')

formCheck.addEventListener('click', function () {
    formCheck.classList.toggle('checkerActive')
})
.checkerActive {
  background-color: red;
}
   <label class="drinos-checker"><input class="drinos-checkbox" type="checkbox" name="checkbox" value="value">Renovation</label>
nicael
  • 18,550
  • 13
  • 57
  • 90
Drinos Shala
  • 105
  • 6
  • 2
    You can probably achieve this with just CSS see: [Highlight label if checkbox is checked](https://stackoverflow.com/questions/5275857/highlight-label-if-checkbox-is-checked) – pilchard Apr 08 '22 at 11:49
  • That would only work if the label comes immediately after the checkbox, in my case label wraps the input, but thanks. – Drinos Shala Apr 08 '22 at 12:33

2 Answers2

4

Instead of adding click event to the label, add it to the input element -

const formCheck = document.querySelector('.drinos-checker');
const inputCheck = document.querySelector('input');

inputCheck.addEventListener('click', function() {
  formCheck.classList.toggle('checkerActive')
})
.checkerActive {
  background-color: red;
}
<label class="drinos-checker"><input class="drinos-checkbox" type="checkbox" name="checkbox" value="value">Renovation</label>
nicael
  • 18,550
  • 13
  • 57
  • 90
Partha Maity
  • 156
  • 4
4

Consider this simple example:

const formCheck = document.querySelector('.check')

formCheck.addEventListener('click', function () {
   console.log("clicked!")
})
<input class="check" type="checkbox">

When you check the checkbox, you can see that the event is captured and then logged.

What happens if we then add a label?

Let's do that. If we then leave the code unchanged, appears that a click on a label does also trigger our click event, though it was binded to the checkbox.

const formCheck = document.querySelector('.check')

formCheck.addEventListener('click', function () {
   console.log("clicked!")
})
<label><input class="check" type="checkbox">A label</label>

That's how it works. But we're not finished yet...

What happens if I bind the event on the label, not on the checkbox?

const formCheck = document.querySelector('label');

formCheck.addEventListener('click', function () {
   console.log("clicked!")
})
<label><input class="check" type="checkbox">A label</label>

You have seen that correct: the click event triggers two times. But how is it even possible? Let's break down what happens here:

  • the label works this way that it triggers a click event in the checkbox
  • once you click the label, the event that you binded is triggered
  • but since the label itself "clicks" the checkbox, the event is triggered again, because the checkbox is in the label. This way, the event is called twice.

So, what does it mean?

You may have understood that already: the class doesn't change because it toggles two times on a single click. I.e. it toggles and then immediately toggles again, which results in you not noticing any changes.

How can one fix that?

There's a quick fix: you could replace your click event with change event. This way:

  • the label triggers checkbox
  • the change event on checkbox is called
  • the label itself doesn't have a change event, thus everything works as intended

"Working-as-intended" example:

const formCheck = document.querySelector('.drinos-checker')

formCheck.addEventListener('change', function () {
    formCheck.classList.toggle('checkerActive')
})
.checkerActive {
  background-color: red;
}
<label class="drinos-checker"><input class="drinos-checkbox" type="checkbox" name="checkbox" value="value">Renovation</label>
nicael
  • 18,550
  • 13
  • 57
  • 90
  • thanks for the explenation, I have another problem I think you could help me understand. I have a parent div with checkboxes wrapped in labels, I have added an event listener to the parent and made it in a way that if the parent is clicked we simply return; and if not the active class is added to the label, everything works fine expect when I actually click on the little box, it triggers the class but it triggers it to the input itself and not the label (where its suppossed to be) – Drinos Shala Apr 11 '22 at 14:24