val () não aciona change () no jQuery

343

Estou tentando acionar o changeevento em uma caixa de texto quando altero seu valor com um botão, mas ele não funciona. Verifique este violino .

Se você digitar algo nas caixas de texto e clicar em outro lugar, changeserá acionado. No entanto, se você clicar no botão, o valor da caixa de texto é alterado, mas changenão é acionado. Por quê?

Ergec
fonte
O próprio título respondeu à minha pergunta. Confirmado em .change () amarelo "Nota: Alterar o valor de um elemento de entrada usando JavaScript, usando .val () por exemplo, não acionará o evento."
Bob Stein
Gostaria de ter encontrado stackoverflow.com/questions/11873721/… mais cedo, espero que ajude alguns.
precisa

Respostas:

454

onchange só é acionado quando o usuário digita a entrada e, em seguida, a entrada perde o foco.

Você pode chamar o onchangeevento manualmente usando depois de definir o valor:

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

Como alternativa, você pode acionar o evento usando:

$("#mytext").trigger("change");
djdd87
fonte
18
fique à vontade para estender o jquery e adicione uma função digamos valWithChange que fará o que você deseja. Não pode ser a ação padrão como muitas vezes você não quer que o fato gerador de uma mudança de valor automatizado, somente quando um usuário interage com o elemento
redsquare
8
Gostaria de ver esta resposta editada para abordar a opção de encadear .change()o .val()método.
Snekse
19
A razão pode ser que algumas pessoas chamam .val()em .change()porque eles fazem validação de entrada. Disparo .change()em .val()causaria um loop infinito.
yingted 2/09/12
7
Somente se eles estivessem alterando o valor para algo que falharia em sua própria validação, o que seria tolo.
Leng
3
Acabei ligação a blurrealizar algo semelhante:$('#mytext').focus().val('New text').blur();
Wes Johnson
63

Da excelente sugestão de redsquare, isso funciona muito bem:

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

$("#my-input").changeVal("Tyrannosaurus Rex");
Chris Fulstow
fonte
5
Você não precisa embrulhar this:return this.val(v).trigger("change");
Sr. Polywhirl 7/17/17
27

Você pode substituir facilmente a valfunção para acionar alterações, substituindo-a por um proxy para a valfunção original .

basta adicionar este código em algum lugar do seu documento (depois de carregar o 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);

Um exemplo de trabalho: aqui

(Observe que isso sempre dispara changequando val(new_val)é chamado, mesmo que o valor não tenha realmente sido alterado.)

Se você deseja ativar SOMENTE a alteração quando o valor realmente mudou, use este:

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

Exemplo ao vivo para isso: http://jsfiddle.net/5fSmx/1/

Yaron U.
fonte
4
Hmm, remendos desnecessários de patos, eu acho :-p. Talvez seja melhor, como comentado pelo redsquare , atribuir a uma função um nome diferente de .val().
binki
11
Se você renomeá-lo, altere o código existente - dessa forma, o código existente continuará funcionando
Yaron U.
4
Mas então todo o código que foi escrito com a definição correta .val()em mente de repente começaria a produzir efeitos colaterais :-p.
binki
2
Isso também irá fazer mau funcionamento plugins, o que pode não ser tão facilmente solucionáveis
SoWhat
11
Para evitar efeitos colaterais, modifiquei a função val como acima, mas estou desencadeando um evento diferente ("val"), que me permite manter o código existente, mas manipulá-lo facilmente sempre que preciso: $ (... ) .on ('change val', ...)
ulu
22

Você precisa encadear o método da seguinte maneira:

$('#input').val('test').change();
Timothy Gonzalez
fonte
11
<3 para o encadeamento!
Gusstavv Gil
14

Não, pode ser necessário acioná-lo manualmente após definir o valor:

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

ou:

$('#mytext').trigger('change');
Darin Dimitrov
fonte
8

Parece que os eventos não estão borbulhando. Tente o seguinte:

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

Eu espero que isso ajude.

Tentei apenas uma idade simples $("#mytext").trigger('change')sem salvar o valor antigo e os .changeincêndios, mesmo que o valor não mudasse. Por isso salvei o valor anterior e liguei $("#mytext").trigger('change')apenas se ele mudar.

Jay Godse
fonte
Surpreendeu que isso não tivesse mais votos, pois é a implementação efetiva atual de uma alteração de elemento HTML.
vol7ron
4

A partir de fevereiro de 2019 .addEventListener()não está mais funcionando com o jQuery .trigger()ou .change(), você pode testá-lo abaixo usando o Chrome ou o 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">

você tem que usar em seu .dispatchEvent()lugar.

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
fonte
1

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

O changeevento é enviado para um elemento quando seu valor é alterado. Este evento é limitado a <input>elementos, <textarea>caixas e <select>elementos. Para caixas de seleção, caixas de seleção e botões de opção, o evento é disparado imediatamente quando o usuário faz uma seleção com o mouse, mas para os outros tipos de elemento, o evento é adiado até que o elemento perca o foco.

Sky Yip
fonte
1

Sei que esse é um tópico antigo, mas para outros que procuram, as soluções acima talvez não sejam tão boas quanto as seguintes, em vez de verificar changeeventos, verifique os inputeventos.

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