val () nie wyzwala zmiany () w jQuery

343

Próbuję wywołać changezdarzenie w polu tekstowym, gdy zmieniam jego wartość za pomocą przycisku, ale nie działa. Sprawdź to skrzypce .

Jeśli wpiszesz coś w polach tekstowych i klikniesz gdzie indziej, changeuruchomi się. Jednak po kliknięciu przycisku wartość pola tekstowego zostanie zmieniona, ale changenie zostanie uruchomiona. Dlaczego?

Ergec
źródło
Sam tytuł odpowiedział na moje pytanie. Potwierdzony w .change () żółty „Uwaga: Zmiana wartości elementu wejściowego za pomocą JavaScript, na przykład za pomocą .val (), nie spowoduje uruchomienia zdarzenia.”
Bob Stein,
Szkoda, że ​​wcześniej nie natknąłem się na stackoverflow.com/questions/11873721 /... Mam nadzieję, że to pomoże.
JeopardyTempest

Odpowiedzi:

454

onchange uruchamia się tylko wtedy, gdy użytkownik wpisze dane wejściowe, a następnie dane wejściowe tracą ostrość.

Możesz ręcznie wywołać onchangezdarzenie po ustawieniu wartości:

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

Alternatywnie możesz uruchomić zdarzenie, używając:

$("#mytext").trigger("change");
djdd87
źródło
18
rozszerzaj jquery i dodaj powiedz funkcję valWithChange, która zrobi to, co chcesz. Nie może to być akcja domyślna, ponieważ wiele razy nie chcesz, aby zdarzenie wyzwalane było z automatycznej zmiany wartości, tylko gdy użytkownik wchodzi w interakcję z elementem
redsquare
8
Chciałbym zobaczyć, jak ta odpowiedź jest edytowana w celu uwzględnienia opcji powiązania .change()z .val()metodą.
Snekse
19
Powodem może być to, że niektórzy ludzie nazywają .val()się .change()bo robią walidacji wejścia. Wyzwalanie .change()na .val()spowodowałaby nieskończoną pętlę.
Yingted
7
Tylko jeśli zmieniliby wartość na coś, co nie udałoby się ich własnej walidacji, co byłoby głupie.
Leng
3
Ostatecznie zobowiązałem się blurdo osiągnięcia czegoś podobnego:$('#mytext').focus().val('New text').blur();
Wes Johnson
63

Z doskonałej sugestii redsquare działa to ładnie:

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

$("#my-input").changeVal("Tyrannosaurus Rex");
Chris Fulstow
źródło
5
Nie trzeba thisreturn this.val(v).trigger("change");
pakować
27

Możesz bardzo łatwo zastąpić valfunkcję, aby wywołać zmianę, zastępując ją proxy do pierwotnej valfunkcji.

po prostu dodaj ten kod gdzieś w swoim dokumencie (po załadowaniu 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);

Działający przykład: tutaj

(Zauważ, że to zawsze zadziała, changegdy val(new_val)zostanie wywołane, nawet jeśli wartość nie uległa zmianie).

Jeśli chcesz wywołać zmianę TYLKO wtedy, gdy wartość faktycznie się zmieniła, użyj tego:

//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);

Przykład na żywo: http://jsfiddle.net/5fSmx/1/

Yaron U.
źródło
4
Hmm, niepotrzebne łatanie kaczek, myślę :-p. Może lepiej, jak komentuje redsquare , nadać takiej funkcji inną nazwę niż .val().
binki
1
Jeśli zmienisz jego nazwę, powinieneś zmienić swój istniejący kod - w ten sposób Twój istniejący kod będzie nadal działał
Yaron U.
4
Ale wtedy cały kod, który został napisany z .val()myślą o prawidłowej definicji , nagle zacząłby wywoływać skutki uboczne :-p.
binki
2
Spowoduje to również nieprawidłowe działanie wtyczek, które mogą nie być tak łatwe do naprawienia
SoWhat
1
Aby uniknąć efektów ubocznych, zmodyfikowałem funkcję val jak wyżej, ale wywołuję inne zdarzenie („val”), które pozwala mi zachować istniejący kod, ale łatwo go obsłużyć, gdy tylko muszę: $ (... ) .Na ( 'val zmiana', ...)
Ulu
22

Musisz połączyć metodę w następujący sposób:

$('#input').val('test').change();
Timothy Gonzalez
źródło
1
<3 dla łańcucha!
Gusstavv Gil
14

Nie, może być konieczne ręczne uruchomienie po ustawieniu wartości:

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

lub:

$('#mytext').trigger('change');
Darin Dimitrov
źródło
8

Wygląda na to, że wydarzenia się nie burzą. Spróbuj tego:

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

Mam nadzieję, że to pomoże.

Próbowałem tylko zwykłego starego $("#mytext").trigger('change')bez zapisywania starej wartości, a .changepożary nawet, jeśli wartość się nie zmieniła. Dlatego zapisałem poprzednią wartość i zadzwoniłem $("#mytext").trigger('change')tylko wtedy, gdy się zmieni.

Jay Godse
źródło
Zaskoczony, że nie miał więcej głosów, ponieważ jest to obecnie skuteczne wdrożenie zmiany elementu HTML.
vol7ron
4

Od lutego 2019 r. .addEventListener()Obecnie nie działa z jQuery .trigger()lub .change()możesz przetestować go poniżej za pomocą Chrome lub Firefox.

txt.addEventListener('input', function() {
  console.log('not called?');
})
$('#txt').val('test').trigger('input');
$('#txt').trigger('input');
$('#txt').change();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="txt">

musisz użyć .dispatchEvent()zamiast tego.

txt.addEventListener('input', function() {
  console.log('it works!');
})
$('#txt').val('yes')
txt.dispatchEvent(new Event('input'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="text" id="txt">

cieunteung
źródło
1

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

changeZdarzenie jest przesyłane do elementu, gdy jego wartość zmienia. To wydarzenie jest ograniczone do <input>elementów, <textarea>pól i <select>elementów. W przypadku pól wyboru, pól wyboru i przycisków opcji zdarzenie jest uruchamiane natychmiast, gdy użytkownik dokonuje wyboru za pomocą myszy, ale w przypadku innych typów elementów zdarzenie jest odraczane do momentu, gdy element straci fokus.

Sky Yip
źródło
1

Wiem, że to stary wątek, ale dla innych, którzy szukają, powyższe rozwiązania mogą nie być tak dobre, jak poniższe, zamiast sprawdzania changezdarzeń, sprawdzania inputzdarzeń.

$("#myInput").on("input", function() {
    // Print entered value in a div box
    $("#result").text($(this).val());
});
Slipoch
źródło