156

I have the following:

<form id="myform">
   <input type="checkbox" name="check1" value="check1">
   <input type="checkbox" name="check2" value="check2">
</form>

How do I use jQuery to capture any check event occuring in myform and tell which checkbox was toggled (and know if it was toggled on or off)?

Kevin B
  • 94,570
  • 16
  • 163
  • 180
aeq
  • 10,377
  • 15
  • 45
  • 46

7 Answers7

284
$('#myform :checkbox').change(function() {
    // this will contain a reference to the checkbox   
    if (this.checked) {
        // the checkbox is now checked 
    } else {
        // the checkbox is now no longer checked
    }
});
SOFe
  • 7,867
  • 4
  • 33
  • 61
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 30
    `this` is already set to the checkbox's DOM element so `this.checked` is sufficient. You won't need to create another jQuery object for it unless you plan on manipulating it. – Walf Oct 13 '11 at 01:43
  • 19
    Just a small tip. You will get a performance boost by using input:checkbox in your selector instead of just :checkbox since the latter is translated to the universal selector *:checkbox. – jimmystormig Feb 01 '12 at 15:28
  • 24
    Click is not anywhere close to *any* check event. – Peter Feb 14 '13 at 14:50
  • 28
    This is no way the best answer. If you have a corresponding label for your input (like `` ) and you click the label, the checkbox will be checked, but this function would NOT be called. You should use the `.change()` event – Patrick Jul 02 '14 at 14:31
  • 7
    This answer does not fully provide the answer - please see Anurag's answer below, which is a MUCH more complete (and accurate) answer. This answer is partly correct of course, but as stated, it is not the best answer. – Carnix Dec 03 '14 at 16:28
  • 5
    This answer (accepted and most upvotes) is insufficient (almost wrong), because the op asked for "*any* check event" and "click" is just one - this function won't be triggered on other checkbox change events... And, of course, people are pointing out the performance impacts (as if it were seconds) of jQuery calls vs. plain JavaScript . See Anurag's answer. – basic6 Jan 09 '15 at 09:34
  • I found I needed to remove the leading space on the : in my selector using the latest jQuery. – PeterT Apr 17 '18 at 22:16
  • this should be inside a $( document ).ready() – Mike W May 04 '21 at 16:49
134

Use the change event.

$('#myform :checkbox').change(function() {
    // this represents the checkbox that was checked
    // do something with it
});
Anurag
  • 140,337
  • 36
  • 221
  • 257
  • If checkbox is hidden, what to do it ? – BILL Mar 13 '12 at 21:40
  • 5
    If the checkbox is hidden, then a user won't be able to interact with it. Let me know if you meant something else. – Anurag Mar 13 '12 at 22:06
  • 1
    This does not fire for `$("input[name=check1]").prop('checked', true)`. See http://jsfiddle.net/Z3E8V/2/ – Peter Feb 14 '13 at 14:58
  • 15
    That is by design. Programmatically changing a DOM element's property does not trigger associated event handlers. You'll have to fire them manually. – Anurag Feb 14 '13 at 15:11
  • 6
    This should be the selected answer, it covers clicking a checkbox's label – Patrick Jul 02 '14 at 14:32
  • 3
    From jQuery documentation: "Because `:checkbox` is a jQuery extension and not part of the CSS specification, queries using `:checkbox` cannot take advantage of the performance boost provided by the native DOM `querySelectorAll()` method. For better performance in modern browsers, use `[type="checkbox"]` instead." – NXT Feb 17 '16 at 09:00
  • Better to use `.change` because the checkbox could be altered with a space bar press if focused. – shrimpwagon Aug 24 '16 at 15:31
58

There are several useful answers, but none seem to cover all the latest options. To that end all my examples also cater for the presence of matching label elements and also allow you to dynamically add checkboxes and see the results in a side-panel (by redirecting console.log).

  • Listening for click events on checkboxes is not a good idea as that will not allow for keyboard toggling or for changes made where a matching label element was clicked. Always listen for the change event.

  • Use the jQuery :checkbox pseudo-selector, rather than input[type=checkbox]. :checkbox is shorter and more readable.

  • Use is() with the jQuery :checked pseudo-selector to test for whether a checkbox is checked. This is guaranteed to work across all browsers.

Basic event handler attached to existing elements:

$('#myform :checkbox').change(function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/2/

Notes:

  • Uses the :checkbox selector, which is preferable to using input[type=checkbox]
  • This connects only to matching elements that exist at the time the event was registered.

Delegated event handler attached to ancestor element:

Delegated event handlers are designed for situations where the elements may not yet exist (dynamically loaded or created) and is very useful. They delegate responsibility to an ancestor element (hence the term).

$('#myform').on('change', ':checkbox', function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/4/

Notes:

  • This works by listening for events (in this case change) to bubble up to a non-changing ancestor element (in this case #myform).
  • It then applies the jQuery selector (':checkbox' in this case) to only the elements in the bubble chain.
  • It then applies the event handler function to only those matching elements that caused the event.
  • Use document as the default to connect the delegated event handler, if nothing else is closer/convenient.
  • Do not use body to attach delegated events as it has a bug (to do with styling) that can stop it getting mouse events.

The upshot of delegated handlers is that the matching elements only need to exist at event time and not when the event handler was registered. This allows for dynamically added content to generate the events.

Q: Is it slower?

A: So long as the events are at user-interaction speeds, you do not need to worry about the negligible difference in speed between a delegated event handler and a directly connected handler. The benefits of delegation far outweigh any minor downside. Delegated event handlers are actually faster to register as they typically connect to a single matching element.


Why doesn't prop('checked', true) fire the change event?

This is actually by design. If it did fire the event you would easily get into a situation of endless updates. Instead, after changing the checked property, send a change event to the same element using trigger (not triggerHandler):

e.g. without trigger no event occurs

$cb.prop('checked', !$cb.prop('checked'));

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/5/

e.g. with trigger the normal change event is caught

$cb.prop('checked', !$cb.prop('checked')).trigger('change');

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/6/

Notes:

  • Do not use triggerHandler as was suggested by one user, as it will not bubble events to a delegated event handler.

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/8/

although it will work for an event handler directly connected to the element:

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/9/

Events triggered with .triggerHandler() do not bubble up the DOM hierarchy; if they are not handled by the target element directly, they do nothing.

Reference: http://api.jquery.com/triggerhandler/

If anyone has additional features they feel are not covered by this, please do suggest additions.

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • I discovered the `.trigger('change')` with this answer. Thanks for this very complete answer ! – Pierre Jan 05 '21 at 15:54
  • +1 on the delegated event handler on children. I actually need this for some complicated dynamic code and you just saved me allot of patchy coding that is far better suited for a parent element. – DarrenMB Jan 16 '21 at 17:05
34

Using the new 'on' method in jQuery (1.7): http://api.jquery.com/on/

    $('#myform').on('change', 'input[type=checkbox]', function(e) {
        console.log(this.name+' '+this.value+' '+this.checked);

    });
  • the event handler will live on
  • will capture if the checkbox was changed by keyboard, not just click
Allen Hamilton
  • 1,148
  • 9
  • 14
  • 1
    This does not fire for `$("input[name=check1]").prop('checked', true)`. See http://jsfiddle.net/Z3E8V/2/ – Peter Feb 14 '13 at 14:59
  • 7
    Just add `.triggerHandler('change');` after the `.prop` call. Then it will toggle the box AND call the event. – Hanna Apr 26 '13 at 22:31
  • an alternative: $(document).on('change','input[type="checkbox"]', function() { $('input[type="checkbox"]').not(this).prop('checked', false); }); – Yoosaf Abdulla Oct 06 '20 at 12:22
6

Acknowledging the fact that the asker specifically requested jQuery and that the answer selected is correct, it should be noted that this problem doesn't actually need jQuery per say. If one desires to solve this problem without it, one can simply set the onClick attribute of the checkboxes that he or she wants to add additional functionality to, like so:

HTML:

<form id="myform">
  <input type="checkbox" name="check1" value="check1" onClick="cbChanged(this);">
  <input type="checkbox" name="check2" value="check2" onClick="cbChanged(this);">
</form>

javascript:

function cbChanged(checkboxElem) {
  if (checkboxElem.checked) {
    // Do something special
  } else {
    // Do something else
  }
}

Fiddle: http://jsfiddle.net/Y9f66/1/

Chase Sandmann
  • 4,795
  • 3
  • 30
  • 42
  • 5
    Putting event handlers directly in the HTML works, of course. But it it is in direct conflict with DRY and progressive enhancement methodologies. A more accurate answer would be "You don't need jQuery to add event handlers" and instead, using standard JS to attach the click handlers in a seperate JS file rather than putting onclick attributes in the HTML. Doing so "works" but good coding practice dictates you should avoid it when possible (which is nearly always at this point unless you must support IE6 or something, which even MS says you shouldn't do anymore) – Carnix Dec 03 '14 at 16:32
5
$('#myform input:checkbox').click(
 function(e){
   alert($(this).is(':checked'))
 }
)
Thinker
  • 14,234
  • 9
  • 40
  • 55
4

I have try the code from first answer, it not working but I have play around and this work for me

$('#vip').change(function(){
    if ($(this).is(':checked')) {
        alert('checked');
    } else {
        alert('uncheck');
    }
});
Somwang Souksavatd
  • 4,947
  • 32
  • 30