ChatGPT解决这个技术问题 Extra ChatGPT

val() doesn't trigger change() in jQuery

I'm trying to trigger the change event on a text box when I change its value with a button, but it doesn't work. Check this fiddle.

If you type something in the text boxes and click somewhere else, change is triggered. However, if you click the button, the text box value is changed, but change doesn't trigger. Why?

Title itself answered my question. Confirmed at .change() yellow "Note: Changing the value of an input element using JavaScript, using .val() for example, won't fire the event."
Wish I'd have come across stackoverflow.com/questions/11873721/… sooner, hope it helps some.
This question must be reopened as popular, and we should mark less popular question as duplicate

E
Eugen Konkov

onchange only fires when the user types into the input and then the input loses focus.

You can manually call the onchange event using after setting the value:

$("#mytext").val( 777 ).change(); // someObject.onchange(); in standard JS

Alternatively, you can trigger the event using:

$("#mytext").val( 777 ).trigger("change");

feel free to extend jquery and add a say valWithChange function that will do what you want. It cannot be the default action as many times you do not want the event triggering from an automated value change, only when a user interacts with the element
I would like to see this answer edited to address the option of chaining .change() to the .val() method.
The reason may be that some people call .val() in .change() because they do input validation. Triggering .change() on .val() would cause an infinite loop.
Only if they were changing the value to something that would fail their own validation, which would be silly.
I ended up binding to blur to accomplish something similar: $('#mytext').focus().val('New text').blur();
F
Florian Lemaitre

From redsquare's excellent suggestion, this works nicely:

$.fn.changeVal = function (v) {
    return this.val(v).trigger("change");
}

$("#my-input").changeVal("Tyrannosaurus Rex");

Y
Yaron U.

You can very easily override the val function to trigger change by replacing it with a proxy to the original val function.

just add This code somewhere in your document (after loading jQuery)

(function($){
    var originalVal = $.fn.val;
    $.fn.val = function(){
        var result =originalVal.apply(this,arguments);
        if(arguments.length>0)
            $(this).change(); // OR with custom event $(this).trigger('value-changed');
        return result;
    };
})(jQuery);

A working example: here

(Note that this will always trigger change when val(new_val) is called even if the value didn't actually changed.)

If you want to trigger change ONLY when the value actually changed, use this one:

//This will trigger "change" event when "val(new_val)" called 
//with value different than the current one
(function($){
    var originalVal = $.fn.val;
    $.fn.val = function(){
        var prev;
        if(arguments.length>0){
            prev = originalVal.apply(this,[]);
        }
        var result =originalVal.apply(this,arguments);
        if(arguments.length>0 && prev!=originalVal.apply(this,[]))
            $(this).change();  // OR with custom event $(this).trigger('value-changed')
        return result;
    };
})(jQuery);

Live example for that: http://jsfiddle.net/5fSmx/1/


Hmm, unnecessary duck-patching, I think :-p. Might be better to, as commented by redsquare, give such a function a different name than .val().
But then all of the code which was written with the correct definition of .val() in mind would suddenly start producing side-effects :-p.
This will also make plugins malfunction, which might not be as easily fixable
In order to avoid side effects, I modified the val function as above, but I'm triggering a different event ("val"), which lets me keep the existing code but easily handle it whenever I need to: $(...).on('change val', ...)
This is an excellent solution in the case you have no control over the code calling .val() like using external library. And if you trigger a custom event, it does not cause any harm.
T
Timothy Gonzalez

You need to chain the method like this:

$('#input').val('test').change();

D
Darin Dimitrov

No you might need to trigger it manually after setting the value:

$('#mytext').change();

or:

$('#mytext').trigger('change');

R
RAM

It looks like the events are not bubbling. Try this:

$("#mybutton").click(function(){
  var oldval=$("#mytext").val();
  $("#mytext").val('Changed by button');
  var newval=$("#mytext").val();
  if (newval != oldval) {
    $("#mytext").trigger('change');
  }
});

I hope this helps.

I tried just a plain old $("#mytext").trigger('change') without saving the old value, and the .change fires even if the value didn't change. That is why I saved the previous value and called $("#mytext").trigger('change') only if it changes.


Surprised this didn't have more votes, since it is the current effective implementation of an HTML element change.
c
cieunteung

As of feb 2019 .addEventListener() is not currently work with jQuery .trigger() or .change(), you can test it below using Chrome or Firefox.

txt.addEventListener('input', function() { console.log('not called?'); }) $('#txt').val('test').trigger('input'); $('#txt').trigger('input'); $('#txt').change();

you have to use .dispatchEvent() instead.

txt.addEventListener('input', function() { console.log('it works!'); }) $('#txt').val('yes') txt.dispatchEvent(new Event('input'));


S
Slipoch

I know this is an old thread, but for others looking, the above solutions are maybe not as good as the following, instead of checking change events, check the input events.

$("#myInput").on("input", function() {
    // Print entered value in a div box
    $("#result").text($(this).val());
});

S
Sky Yip

From https://api.jquery.com/change/:

The change event is sent to an element when its value changes. This event is limited to <input> elements, <textarea> boxes and <select> elements. For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.