2011-01-12 19 views
338

La lógica en el controlador de eventos change() no se está ejecutando cuando el valor está establecido en val(), pero se ejecuta cuando el usuario selecciona un valor con el mouse. ¿Por qué es esto?¿Por qué el evento de cambio de jquery no se activa cuando establezco el valor de una selección usando val()?

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

Respuesta

534

Porque el evento change requiere un evento de navegador real iniciado por el usuario en lugar de mediante el código de javascript.

hacer esto en su lugar:

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

Hola, haciendo esta actualización desplegable. pero ser llamado onChange() recursivamente. – Pankaj

+3

Busco esta respuesta. Funciona, pero ¿no hay una mejor manera con jQuery? Estoy seguro de que TODOS recordaremos hacer esto cada vez que cambiemos un valor que tiene un controlador de cambio configurado (sarcasmo). Los marcos que usan el enlace de datos podrían resolver esto mejor? – Jess

+0

@ user113716 ¿Sabría cómo manipularlo sin conocer ningún valor? – BKSpurgeon

43

Creo que se puede activar manualmente el evento de cambio con trigger():

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

Aunque por lo que no se dispara de forma automática, no tengo ni idea.

+0

no soy capaz de hacer funcionar esto, también $ ("# única") Val ("Single2") cambio(); Estoy creando dinámicamente el menú desplegable y cambiando su valor (Funciona bien para mí) Pero cuando intento activar el cambio, no funciona para mí. –

+4

Un "bit" tardío pero no se dispara automáticamente porque daría lugar a bucles infinitos. Piensa '$ ('# foo'). Change (function() {$ (this) .val ('whatever');});' – JJJ

+0

@Juhana Creo que un ciclo infinito es mucho más fácil de detectar, diagnosticar y corregir que val() misteriosamente no puede desencadenar enlaces de "cambio". – iono

8

Por lo que yo puedo leer en la API. El evento solo se activa cuando el usuario hace clic en una opción.

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

Para cuadros de selección, casillas de verificación, y botones de radio, el evento se dispara inmediatamente cuando el usuario realiza una selección con el ratón, pero para los demás tipos de elementos del evento es diferido hasta que el elemento pierde foco.

+0

¿Cuáles son las alternativas para los otros tipos de elementos? Quiero que el evento de "cambio" se active inmediatamente para los elementos de 'entrada', no cuando el elemento pierde el foco. ¿Tú sabes? –

+1

Si con "inmediatamente" quiere decir "cada vez que se presiona una tecla en la entrada" está buscando los eventos onkeyup, onkeypress y onkeydown, no en el cambio. – user2867288

8

La adición de este pedazo de código después del val() parece funcionar:

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

Sí, pero no necesita hacer una selección de DOM por separado con '$ (": input # single ")'. De hecho, realmente no deberías. Simplemente enchúfalo después del '.val() '. Puede usar '.trigger ('change')' o '.change()'. Ellos son exactamente lo mismo. – user113716

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

Esto funcionó para mi guión. Tengo 3 combos & enlazar con evento chainSelect, necesito pasar 3 valores por url & por defecto seleccionar todo desplegable. Utilicé esto

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

Y el primer evento funcionó.

+10

Espero que nunca hagas esto en el mundo real. Huelga decir que $ _GET ['whatever'] no se puede confiar. –

3

En caso de que no quiere mezclar con evento de cambio predeterminado que puede proporcionar a su evento personalizado

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

para desencadenar el evento el conjunto de valores, puede hacerlo

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

Si acaba de agregar la opción de selección a un formulario y desea desencadenar el evento de cambio, he encontrado que se requiere un setTimeout; de lo contrario, jQuery no selecciona el cuadro de selección recién agregado:

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

Para que sea más fácil añadir una función personalizada y lo llaman cuando cada vez que desea que el cambio de valor también desencadenar el cambio

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

y

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

o se puede reemplazar la función val para llamar siempre el cambio cuando la val se llama

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

muestra a http://jsfiddle.net/r60bfkub/

+0

Mi navegador se queja de demasiada recursión, ¿alguna solución para esto? –

+0

Está escuchando el '' 'change'''-event sobre un control y está ejecutando una devolución de llamada que (directa o indirectamente) activa nuevamente el' '' change'''-event sobre el mismo control. Te sugiero que uses otro nombre para el evento que disparas manualmente (por ejemplo, '' 'explicit.change'''), para que no vuelva a activar el' '' change'''-event, evite el bucle y aún te permite reaccionar al evento. – Kamafeather

1

Me encontré con el mismo problema al usar CMB2 con Wordpress y quería conectarme al evento de cambio de un metabox de carga de archivos.

En caso de que no pueda modificar el código que invoca el cambio (en este caso, el script CMB2), use el siguiente código. El desencadenante se invoca DESPUÉS de que se establezca el valor; de lo contrario, su change eventHandler funcionará, pero el valor será el anterior, no el que se está configurando.

Aquí está el código que utilizo:..

(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); 
Cuestiones relacionadas