1252748
1252748

Reputation: 15369

checkbox checked with prop() does not fire events attached to "change"

boxes checked using jQuery prop() do not affect listeners attached to change handler.

My code is something like

HTML

<div>
    <label>
        <input type="checkbox" class="ch" />test</label>
    <label>
        <input type="checkbox" class="ch" />test</label>
    <label>
        <input type="checkbox" class="ch" />test</label>
    <input type="button" value="check the box" id="select" />
</div>

JS

 $("body").on("change", ".ch", function(){

  alert("checked");

});


$("body").on("click", "#select", function(){

  $(this).parent("div").find("input[type=checkbox]").prop("checked", true);

});

the alert fires when I click on the checkbox. How can I make it fire when the property of the checkbox changes? JSBIN

Upvotes: 26

Views: 16352

Answers (3)

Shaun Cockerill
Shaun Cockerill

Reputation: 926

In most cases, triggering the change event when you update a property should be the accepted answer, however, there are some instances where properties are adjusted, and you do not have the luxury to add a trigger function call. A common example is when a script is hosted externally.

The below snippet will use the current jQuery prop function to get and/or change the property value, but will also trigger two events, one before property is changed, and another for after the property has been changed. Both the property name and alternating value will also be passed.

jQuery(function(){
    var _oldProp = jQuery.fn.prop;
    jQuery.fn.extend({prop: function( prop, val ) {
        // Only trigger events when property is being changed
        if ( val !== undefined ) {
            this.trigger( 'propChange', [prop, val] );     // before change listener
            var oldVal = this.prop( prop );                // Get old Value
            var ret = _oldProp.call( this, prop, val );    // Update Property
            this.trigger( 'propChanged', [prop, oldVal] ); // after change listener
            return ret;
        }
        return _oldProp.call( this, prop );
    }});
});

Then in order to capture the change event, you can bind into either listener, and even compare the property name and old value (or new value if you hook into the before event) as required.

jQuery('input[type="checkbox"]').on('propChanged', function( event, prop, oldVal ) {
    if ( prop === 'checked' && oldVal !== jQuery(this).prop( prop ) ) {
        jQuery(this).trigger('change');
    }
});

This can be used for any property, and is also not just limited to checkboxes and change events. The same snippet above can also be copied to work with the jQuery(el).attr(attr,val) function.

Upvotes: 0

Todd
Todd

Reputation: 1674

Trigger the event from inside your function:

$("body").on("click", "#select", function(){
  $(this).parent("div").find("input[type=checkbox]").prop("checked", true).trigger("change");
});

Upvotes: 7

Sergio
Sergio

Reputation: 28845

You have to use .change() to trigger the change event listener:

$("body").on("change", ".ch", function () {
    alert("checked");
});


$("body").on("click", "#select", function () {
    $(this).parent("div").find("input[type=checkbox]").prop("checked", true).change();
});

JSBbin or Fiddle

Please note that this will fire many events. Three in the html example you have in jsBin.

Upvotes: 32

Related Questions