Divyang
Divyang

Reputation: 392

Checkbox not working normally in case of event.preventDefault and just working when using setTimeout

I was just going through a scenario where I needed to customize a checkbox so that should not be checked instantly, rather,

  1. Show a confirm box, when a user tries to check a checkbox.
  2. If the user clicks Yes, the checkbox is checked.
  3. On click of No, checkbox does not change and remains unchecked.

While working on that, I used preventDefault followed by stopPropagation to stop the checkbox from following default behavior and make it checked or unchecked conditionally.

In the following snippet, the checkbox is getting checked at first, but then it is not un-checking, given the code is working fine with setTimeout but not without it. Following is the mockup:

$(document).ready(function() {
  $('#chkbx').off('click').on('click', function(e) {
    var $checkbox = $(this);
    e.preventDefault();
    e.stopPropagation();
    showConfirmation($checkbox.is(':checked') ? 1 : 0);
  });

  function showConfirmation(s_checked) {
    // Why this if block is making checkbox checked 
    if (s_checked) {
      setTimeout(function() {
        $('#chkbx').val(1);
        $('#chkbx').prop('checked', true);
      }, 3000);
      // While a similar code without delay is not working
    } else {
      $('#chkbx').val(0);
      $('#chkbx').prop('checked', false);
    }
    return true;
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" id="chkbx" name="chkbx" />

Please help me understand, what is going wrong here due to which the code is not unchecking the checkbox when not using setTimeout.

Upvotes: 2

Views: 1925

Answers (2)

Scott Marcus
Scott Marcus

Reputation: 65825

I think you are taking the wrong approach here. Instead of e.preventDefault() and timers, you can just disable the checkbox until the "some other button" that you refer to gets pressed.

$(document).ready(function() {
  var $checkbox = $("#chkbx");
  
  // Simply set up your button click event
  $('button').on('click', function(e) {
    $checkbox.removeAttr("disabled"); // Enable the checkbox
  });
  
  $checkbox.on("click", showConfirmation);

  function showConfirmation(event) {
    console.log("The checkbox is checked: " + event.target.checked);
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Click to enable</button>
<input type="checkbox" id="chkbx" name="chkbx" disabled>Some question

Upvotes: 0

Wazeed
Wazeed

Reputation: 1280

event.preventDefault() method prevents default action. In the case of clicking a checkbox, the default action is toggling its checked state, which is getting prevented in the code in question. With setTimeout the code is actually getting executed after the click event has finished, so preventDefault is not being observed.

However, to make this work, you may choose to use event.preventDefault() only when you really want to prevent the checkbox toggling. Check out the below snippet:

$(document).ready(function() {
  $('#chkbx').on('click', function(e) {
    var $checkbox = $(this);
    e.stopPropagation();
    
    if($checkbox.is(":checked")) {
      if(confirm('Do you want to check?')) {
        $checkbox.val(1);
      } else {
        // use `preventDefault()` to block checkbox checking when not confirmed
        e.preventDefault();
      }
    } else {
      $checkbox.val(0);
    }
  });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label><input type="checkbox" id="chkbx" name="chkbx" value="0"/> Checkbox Label</label>

Upvotes: 1

Related Questions