Ivan
Ivan

Reputation: 433

On element click Trigger event fire twice for input checkbox

when i click on the div element should trigger click on checkbox only once but for some reason i get event fired twice , i saw other topics with similar problem but noone helped me

$('div').click(function(e) {
  $('input').trigger('click');

  check();
});

function check() {
  if ($('input').is(':checked')) {
    console.log('input cheked')
  } else {
    console.log('unchecked')
  }
}
.test {
  height: 150px;
  width: 150px;
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test">
  <input type="checkbox" name="">
</div>

Upvotes: 2

Views: 3123

Answers (4)

CaeSea
CaeSea

Reputation: 298

JQuery uses event bubbling when setting up events. This means that when you click the input the event is fired once for the input and then it 'bubbles' up the DOM tree to the parent DIV. This then notices the click event on the DIV and fires again. Therefore the event fires twice, once for the input and again for the DIV.

To stop this you will need to use the 'capture' technique instead of event bubbling. This would mean that you would use addEventListener and pass in the option as the third argument as true.

See here: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Also see here to understand bubbling vs capturing: https://javascript.info/bubbling-and-capturing

Upvotes: 0

Mayur Patel
Mayur Patel

Reputation: 1751

Your checkbox is inside div and you are binding click evet to div and from that you are triggering checkbox click event which again triggers click of div. That's why it's triggering 2 times.

You can directly go for checkbox change event:

$(':checkbox').on('change', function() {
  if (this.checked) {
    console.log('input checked')
  } else {
    console.log('unchecked')
  }
});
.test{
  height: 150px;
  width: 150px;
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test">
	<input type="checkbox" name="">
</div>

Upvotes: 0

Archie
Archie

Reputation: 911

That is because, when you are trigerring click on the input the event is being bubbles to all its parents. To stop that use e.stopPropagation on the click event handler of input.

$('input').click(function(e) {
  e.stopPropagation();
});

Read more about bubbling and capturing here.

Check the working code below:

$('div').click(function(e) {
  $('input').trigger('click');
  check();
});

$('input').click(function(e) {
  e.stopPropagation();
});


function check() {
  if ($('input').is(':checked')) {
    console.log('input cheked')
  } else {
    console.log('unchecked')
  }
}
.test {
  height: 150px;
  width: 150px;
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test">
  <input type="checkbox" name="">
</div>

Upvotes: 1

Rory McCrossan
Rory McCrossan

Reputation: 337580

The issue is because the click occurs on the div, which triggers a click on the child checkbox which in turn propagates up the DOM and runs the click handler on the div again.

If you are trying to create a bigger hit-area for the checkbox, just use a label element instead. Then you get this behaviour for free without needing any JS.

If you want to know the state of a checkbox when it's changed, hook a change event handler to it. Try this:

$(':checkbox').on('change', function() {
  if (this.checked) {
    console.log('input checked')
  } else {
    console.log('unchecked')
  }
});
.test {
  height: 150px;
  width: 150px;
  background: red;
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label class="test">
  <input type="checkbox" name="">
</label>

Upvotes: 5

Related Questions