Home > Mobile >  Click event on label not firing (class doesn't change)
Click event on label not firing (class doesn't change)

Time:04-09

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 ><input  type="checkbox" name="checkbox" value="value">Renovation</label>

CodePudding user response:

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 ><input  type="checkbox" name="checkbox" value="value">Renovation</label>

CodePudding user response:

Consider this simple example:

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

formCheck.addEventListener('click', function () {
   console.log("clicked!")
})
<input  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  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  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 ><input  type="checkbox" name="checkbox" value="value">Renovation</label>

CodePudding user response:

A CSS Only Solution

OP has already selected an answer, but I was still curious if this could be done only with CSS and no JavaScript. The advantage is significant as it just automatically works everywhere by applying a class and with as many checkboxes as you need without having to attach event handlers to each one.

The only change, aside from the css, is to add a div which is used for background color. Run the snippet to see how it works.

.drinos {
  position: relative;
  padding: 0.25em;
  margin: 0.5em;
}

.drinos div {
  position: absolute;
  z-index: -1;
  border-radius: 0.25em;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  transition: transform 0.5s, background-color 0.5s;
}

.drinos input:checked   div {
  background-color: pink;
  transform: scaleX(-1);
}
<label >
  <input type="checkbox"> Renovation 1
  <div></div>
</label>
<label >
  <input type="checkbox"> Renovation 2
  <div></div>
</label>
<label >
  <input type="checkbox"> Renovation 3
  <div></div>
</label>
<label >
  <input type="checkbox"> Renovation 4
  <div></div>
</label>

  • Related