val () ne déclenche pas change () dans jQuery

343

J'essaie de déclencher l' changeévénement sur une zone de texte lorsque je modifie sa valeur avec un bouton, mais cela ne fonctionne pas. Vérifiez ce violon .

Si vous tapez quelque chose dans les zones de texte et cliquez ailleurs, changeest déclenché. Cependant, si vous cliquez sur le bouton, la valeur de la zone de texte est modifiée, mais changene se déclenche pas. Pourquoi?

Ergec
la source
Le titre lui-même a répondu à ma question. Confirmé à .change () jaune "Remarque: la modification de la valeur d'un élément d'entrée à l'aide de JavaScript, à l'aide de .val () par exemple, ne déclenchera pas l'événement."
Bob Stein
J'aimerais avoir rencontré stackoverflow.com/questions/11873721/… plus tôt, j'espère que cela aide certains.
JeopardyTempest

Réponses:

454

onchange ne se déclenche que lorsque l'utilisateur tape dans l'entrée, puis que l'entrée perd le focus.

Vous pouvez appeler manuellement l' onchangeévénement en utilisant après avoir défini la valeur:

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

Alternativement, vous pouvez déclencher l'événement en utilisant:

$("#mytext").trigger("change");
djdd87
la source
18
n'hésitez pas à étendre jquery et à ajouter une fonction disons valWithChange qui fera ce que vous voulez. Il ne peut pas s'agir de l'action par défaut tant de fois que vous ne voulez pas que l'événement se déclenche à partir d'un changement de valeur automatisé, uniquement lorsqu'un utilisateur interagit avec l'élément
redsquare
8
Je voudrais voir cette réponse modifiée pour aborder l'option de chaînage .change()à la .val()méthode.
Snekse
19
La raison peut être que certaines personnes appellent .val()à .change()parce qu'ils font la validation d' entrée. Déclencher .change()dessus .val()entraînerait une boucle infinie.
décédé le
7
Seulement s'ils changeaient la valeur en quelque chose qui échouerait à leur propre validation, ce qui serait idiot.
Leng
3
J'ai fini par m'engager blurà accomplir quelque chose de similaire:$('#mytext').focus().val('New text').blur();
Wes Johnson
63

D'après l'excellente suggestion de redsquare, cela fonctionne bien:

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

$("#my-input").changeVal("Tyrannosaurus Rex");
Chris Fulstow
la source
5
Vous n'avez pas besoin d'envelopper this:return this.val(v).trigger("change");
M. Polywhirl
27

Vous pouvez très facilement remplacer la valfonction pour déclencher le changement en la remplaçant par un proxy de la valfonction d' origine .

il suffit d'ajouter ce code quelque part dans votre document (après le chargement de 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);

Un exemple concret : ici

(Notez que cela se déclenchera toujours changelorsqueval(new_val) est appelé même si la valeur n'a pas réellement changé.)

Si vous souhaitez déclencher le changement UNIQUEMENT lorsque la valeur a réellement changé, utilisez celui-ci:

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

Exemple en direct pour cela: http://jsfiddle.net/5fSmx/1/

Yaron U.
la source
4
Hmm, patchs de canard inutiles, je pense :-p. Il serait peut-être préférable, comme l'a commenté redsquare , de donner à une telle fonction un nom différent de .val().
binki
1
Si vous le renommez, vous devez modifier votre code existant - de cette façon, votre code existant continuera de fonctionner
Yaron U.
4
Mais alors tout le code qui a été écrit avec la définition correcte de l' .val()esprit commencerait soudainement à produire des effets secondaires :-p.
binki
2
Cela entraînera également un dysfonctionnement des plugins, qui pourrait ne pas être aussi facilement
réparable
1
Afin d'éviter les effets secondaires, j'ai modifié la fonction val comme ci-dessus, mais je déclenche un événement différent ("val"), ce qui me permet de conserver le code existant mais de le gérer facilement chaque fois que je dois: $ (... ) .on ('change val', ...)
ulu
22

Vous devez enchaîner la méthode comme ceci:

$('#input').val('test').change();
Timothy Gonzalez
la source
1
<3 pour l'enchaînement!
Gusstavv Gil
14

Non, vous devrez peut-être le déclencher manuellement après avoir défini la valeur:

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

ou:

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

Il semble que les événements ne bouillonnent pas. Essaye ça:

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

J'espère que ça aide.

J'ai essayé un simple vieux $("#mytext").trigger('change')sans sauvegarder l'ancienne valeur, et les .changeincendies même si la valeur n'a pas changé. C'est pourquoi j'ai enregistré la valeur précédente et appelé $("#mytext").trigger('change')uniquement si elle change.

Jay Godse
la source
Surpris, cela n'a pas eu plus de votes, car c'est la mise en œuvre effective actuelle d'un changement d'élément HTML.
vol7ron
4

À partir de février 2019, il .addEventListener()ne fonctionne pas actuellement avec jQuery .trigger()ou .change(), vous pouvez le tester ci-dessous en utilisant Chrome ou 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">

vous devez utiliser à la .dispatchEvent()place.

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
la source
1

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

L' changeévénement est envoyé à un élément lorsque sa valeur change. Cet événement est limité aux <input>éléments, <textarea>boîtes et <select>éléments. Pour les cases de sélection, les cases à cocher et les boutons radio, l'événement est déclenché immédiatement lorsque l'utilisateur effectue une sélection avec la souris, mais pour les autres types d'élément, l'événement est différé jusqu'à ce que l'élément perd le focus.

Sky Yip
la source
1

Je sais que c'est un vieux fil de discussion, mais pour ceux qui recherchent, les solutions ci-dessus ne sont peut-être pas aussi bonnes que les suivantes, au lieu de vérifier les changeévénements, vérifiez les inputévénements.

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