Perché l'evento di modifica jQuery non si attiva quando imposto il valore di una selezione utilizzando val ()?


La logica nel gestore di eventi change() non viene eseguita quando il valore è impostato da val() , ma viene eseguito quando l'utente seleziona un valore con il mouse. Perchè è questo?

<select id="single">
    <option>Single</option>
    <option>Single2</option>
</select>

<script>
    $(function() {
        $(":input#single").change(function() {
           /* Logic here does not execute when val() is used */
        });
    });

    $("#single").val("Single2");
</script>


Answers


Poiché l'evento change richiede un evento del browser effettivo avviato dall'utente anziché tramite il codice javascript.

Fatelo invece:

$("#single").val("Single2").trigger('change');



Credo che tu possa attivare manualmente l'evento change con trigger() :

$("#single").val("Single2").trigger('change');

Anche se il motivo per cui non si attiva automaticamente, non ne ho idea.




Per quanto posso leggere in API. L'evento viene attivato solo quando l'utente fa clic su un'opzione.

http://api.jquery.com/change/

Per le caselle di selezione, le caselle di controllo e i pulsanti di opzione, l'evento viene attivato immediatamente quando l'utente effettua una selezione con il mouse, ma per gli altri tipi di elemento l'evento viene posticipato fino a quando l'elemento non si concentra.




Aggiungere questo pezzo di codice dopo il val () sembra funzionare:

$(":input#single").trigger('change');



Per facilitare l'aggiunta di una funzione personalizzata e chiamarla quando vuoi, anche la modifica del valore innesca il cambiamento

$.fn.valAndTrigger = function (element) {
    return $(this).val(element).trigger('change');
}

e

$("#sample").valAndTirgger("NewValue");

Oppure puoi sovrascrivere la funzione val per chiamare sempre la modifica quando viene chiamato val

(function ($) {
    var originalVal = $.fn.val;
    $.fn.val = function (value) {
        this.trigger("change");
        return originalVal.call(this, value);
    };
})(jQuery);

Esempio su http://jsfiddle.net/r60bfkub/




Nel caso in cui non si desideri confondere l'evento di modifica predefinito, è possibile fornire il proprio evento personalizzato

$('input.test').on('value_changed', function(e){
    console.log('value changed to '+$(this).val());
});

per attivare l'evento sul set di valori, puoi farlo

$('input.test').val('I am a new value').trigger('value_changed');



$(":input#single").trigger('change');

Questo ha funzionato per la mia sceneggiatura. Ho 3 combo e bind con l'evento chainSelect, ho bisogno di passare 3 valori da url e default selezionare tutto a tendina. L'ho usato

$('#machineMake').val('<?php echo $_GET['headMake']; ?>').trigger('change');

E il primo evento ha funzionato.




Mi sono imbattuto nello stesso problema durante l'utilizzo di CMB2 con Wordpress e volevo collegarmi all'evento di modifica di un metabox di caricamento file.

Quindi, se non sei in grado di modificare il codice che invoca la modifica (in questo caso lo script CMB2), utilizza il codice seguente. Il trigger viene richiamato DOPO aver impostato il valore, altrimenti la modifica eventHandler funzionerà, ma il valore sarà il precedente, non quello impostato.

Ecco il codice che uso:

(function ($) {
    var originalVal = $.fn.val;
    $.fn.val = function (value) {
        if (arguments.length >= 1) {
            // setter invoked, do processing
            return originalVal.call(this, value).trigger('change');
        }
        //getter invoked do processing
        return originalVal.call(this);
    };
})(jQuery);



Se hai appena aggiunto l'opzione select a un modulo e desideri attivare l'evento change, ho trovato che setTimeout è richiesto altrimenti jQuery non preleva la casella di selezione appena aggiunta:

window.setTimeout(function() { jQuery('.languagedisplay').change();}, 1);