jQuery val( val ) and the absence of onChange firing

Some coworkers and myself have run into some confusion using the val( val ) function of jQuery to set the value of a control, and finding that the control's onChange event does not fire.

First of all, onChange is implemented differently between Firefox and IE.  In IE, onChange for a select box fires right as the value of the select is changed.  Some say that this implementation is incorrect and that the onChange event is supposed to fire after the control looses focus.  Firefox implements the event the other way.  I've not checked the W3C specs to see which is correct, because frankly I don't care. What I do care about is that I have to deal with the inconsistency.

So taking the implementation into consideration, when you want to set the value of a control using $("myInput").val(newValue);, the onChange not firing makes sense. We're not using val to tell the form to set the value of the control and then make it loose focus.  Perhaps onChange should have been named OnAfterChange instead, but that's besides the point.

To get the behavior we're looking for, set the value then fire the onChange event of the control, we have to call .change() after val( val ).

        function setViajQuery() {
            $("#myInput").val("1");
            $("#myInput").change();
        }

This gives us the behavior we're looking for.

We could easily wrap this in a function to use whenever we're expecting onChange to be fired:

        function setValAndFireOnChange(jQueryObj, newVal) {
            jQueryObj.val(newVal);
            jQueryObj.change();
        }
 
        function setViajQuery() {
            setValAndFireOnChange($("#myInput"), "1");
        }
 

Alternatively, let's extend jQuery:

        (function($) {
            $.fn.valChange = function(newValue) {
                return this.each(function() {
                    var obj = $(this);
                    obj.val(newValue);
                    obj.change();
                });
            };
        })(jQuery);

The code is the same, but instead of the calling syntax being setValAndFireOnChange($("#myInput"), "1");, we can have the same effect gracefully:

            $("#myInput").valChange("1");

The benefit of extending jQuery is that we can respect jQuery's chaining:

            $("#myInput").valChange("1").css("background","blue");


Posted by: Jeff
Posted on: 6/5/2009 at 10:52 PM
Tags:
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (6) | Post RSSRSS comment feed

Comments

Russell Heimlich United States

Tuesday, August 11, 2009 10:48 PM

Russell Heimlich

Couldn't you just use the onblur event handler rather than onchange?

Citizen Ecodrive United States

Thursday, November 05, 2009 10:41 AM

Citizen Ecodrive

Couldn't you just use the onblur event handler rather than onchange

Jeff United States

Monday, November 09, 2009 6:09 PM

Jeff

Good points guys, the reason I had to come up with this solution was that onblur occurs on loss of focus, and in this situation, there was no loss of focus, because the value of the control was being set via code.

acai berry lose weight United States

Wednesday, February 17, 2010 9:08 AM

acai berry lose weight

There is more to life than increasing its speed.

teeth whitening free kit United States

Wednesday, February 17, 2010 9:25 AM

teeth whitening free kit

Questions provide the key to unlocking our unlimited potential.

colorado springs mortgage United States

Thursday, February 18, 2010 10:56 AM

colorado springs mortgage

This really is a amazing posting, i'm happy I ran across. I've been seeking visitor writters for my blogs so if you ever decide thats something you are interested in please feel free to contact me. I will be back to look at out more of your articles later!

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading