Dragoniez
Dragoniez

Reputation: 27

Nested events triggered multiple times

I have a question about a code like the following:

$(function() {
  var checkboxCnt = 1;
  var checkboxHtml =
    `<br><input type="checkbox" id="checkbox${checkboxCnt}">` +
    `<label for="checkbox${checkboxCnt}">Checkbox 1</label>`;

  // ******************************************
  $('div :checkbox').change(function(e) {
    checkboxChanged(e);
  });
  // ******************************************

  $('#btn').click(function() {
    checkboxCnt++;
    checkboxHtml = checkboxHtml.replaceAll(checkboxCnt - 1, checkboxCnt);
    $(this).before($(checkboxHtml));

    // ******************************************
    $('div :checkbox').change(function(e) {
      checkboxChanged(e);
    });
    // ******************************************
  });

  function checkboxChanged(e) {
    var checkboxID = '#' + e.target.id;
    if ($(checkboxID).is(':checked')) {
      console.log(checkboxID + ' is checked');
    } else {
      console.log(checkboxID + ' is unchecked');
    }
  }

});
#btn {
  width: 100px;
  height: 100px;
  background-color: yellow;
  display: block;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>

<div>
  <input type="checkbox" id="checkbox1">
  <label for="checkbox1">Checkbox 1</label>
  <button type="button" id="btn">Click Me!</button>
</div>

Sample can be found on https://jsfiddle.net/da7wLukz/.

This is just a simplified version of the code I'm currently editing, and it adds a checkbox every time when you hit the button. I want to execute something every time when the checkboxes are (un)checked, but I've come across the problem that when you have 4 checkboxes and check the checkbox4, the change event is triggered only once but when you check the checkbox3, it's triggered twice, and when you check the checkbox2, it's triggered 3 times and so on. The code has the same lines inside and outside of $('#btn).click because, let's say we don't have the $('div :checkbox).change event inside the $('#btn).click event, then the change event isn't triggered when checkbox2, 3, 4... are checked.

I just want the change event to be triggered only once when I (un)check the checkbox, but how can I do this? Thank you for your help in advance.

Upvotes: 0

Views: 83

Answers (1)

Tomalak
Tomalak

Reputation: 338228

Don't nest event handlers. Use unobtrusive event handling via $(document).on() (docs):

$(function() {
  var checkboxCnt = 0;
  var checkboxHtml =
    `<input type="checkbox" id="checkbox$%%">` +
    `<label for="checkbox$%%">Checkbox %%</label><br>`;
    
  function addCheckbox() {
    checkboxCnt++;
    $("#btn").before(checkboxHtml.replaceAll('%%', checkboxCnt));
  }

  $(document).on('change', 'div :checkbox', function () {
    if (this.checked) {
      console.log(this.id + ' is checked');
    } else {
      console.log(this.id + ' is unchecked');
    }
  });

  $('#btn').click(addCheckbox);
  addCheckbox();
});
#btn {
  width: 100px;
  height: 100px;
  background-color: yellow;
  display: block;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>

<div>
  <button type="button" id="btn">Click Me!</button>
</div>

Upvotes: 1

Related Questions