val () no activa el cambio () en jQuery

343

Estoy tratando de activar el changeevento en un cuadro de texto cuando cambio su valor con un botón, pero no funciona. Mira este violín .

Si escribe algo en los cuadros de texto y hace clic en otro lugar, changese activa. Sin embargo, si hace clic en el botón, el valor del cuadro de texto cambia, pero changeno se activa. ¿Por qué?

Ergec
fuente
El título en sí respondió a mi pregunta. Confirmado en .change () amarillo "Nota: Cambiar el valor de un elemento de entrada usando JavaScript, usando .val () por ejemplo, no activará el evento".
Bob Stein
Ojalá hubiera encontrado stackoverflow.com/questions/11873721/… antes, espero que ayude un poco.
JeopardyTempest

Respuestas:

454

onchange solo se activa cuando el usuario escribe en la entrada y luego la entrada pierde el foco.

Puede llamar manualmente al onchangeevento usando después de configurar el valor:

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

Alternativamente, puede activar el evento usando:

$("#mytext").trigger("change");
djdd87
fuente
18
siéntase libre de extender jquery y agregar una función say valWithChange que hará lo que desee. No puede ser la acción predeterminada tantas veces que no quiere que el evento desencadenante de un cambio automático de valor, sólo cuando un usuario interactúa con el elemento
redsquare
8
Me gustaría ver esta respuesta editada para abordar la opción de encadenar .change()al .val()método.
Snekse
19
La razón puede ser que algunas personas llaman .val()en .change()porque lo hacen de validación de entrada. Desencadenando .change()en .val()provocaría un bucle infinito.
gritó el
77
Solo si cambiaran el valor a algo que fallara su propia validación, lo cual sería una tontería.
Leng
3
Terminé atado para blurlograr algo similar:$('#mytext').focus().val('New text').blur();
Wes Johnson
63

De la excelente sugerencia de redsquare, esto funciona muy bien:

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

$("#my-input").changeVal("Tyrannosaurus Rex");
Chris Fulstow
fuente
55
No necesita envolver this:return this.val(v).trigger("change");
Sr. Polywhirl
27

Puede anular fácilmente la valfunción para activar el cambio reemplazándola con un proxy de la valfunción original .

simplemente agregue este código en algún lugar de su documento (después de cargar 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 ejemplo de trabajo: aquí

(Tenga en cuenta que esto siempre se activará changecuando val(new_val)se llame, incluso si el valor no cambió realmente).

Si desea activar el cambio SOLO cuando el valor realmente cambió, 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);

Ejemplo en vivo para eso: http://jsfiddle.net/5fSmx/1/

Yaron U.
fuente
44
Hmm, parches de pato innecesarios, creo :-p. Podría ser mejor, como comentó redsquare , darle a esa función un nombre diferente que .val().
binki
1
Si le cambia el nombre, debe cambiar su código existente, de esta manera su código existente seguirá funcionando
Yaron U.
44
Pero entonces todo el código que fue escrito con la definición correcta de .val()en mente de repente comenzaría a producir efectos secundarios :-p.
binki
2
Este mal funcionamiento plugins también hará, lo que podría no ser tan fácil solución
SoWhat
1
Para evitar efectos secundarios, modifiqué la función val como se indicó anteriormente, pero estoy activando un evento diferente ("val"), que me permite mantener el código existente pero manejarlo fácilmente cada vez que necesito: $ (... ) .on ('change val', ...)
ulu
22

Necesita encadenar el método de esta manera:

$('#input').val('test').change();
Timothy Gonzalez
fuente
1
<3 para el encadenamiento!
Gusstavv Gil
14

No, es posible que deba activarlo manualmente después de establecer el valor:

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

o:

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

Parece que los eventos no están burbujeando. Prueba esto:

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

Espero que esto ayude.

Intenté simplemente un viejo $("#mytext").trigger('change')sin guardar el valor anterior, y los .changeincendios incluso si el valor no cambió. Es por eso que guardé el valor anterior y llamé $("#mytext").trigger('change')solo si cambia.

Jay Godse
fuente
Sorprendido, esto no tuvo más votos, ya que es la implementación efectiva actual de un cambio de elemento HTML.
vol7ron
4

A partir de febrero de 2019, .addEventListener()actualmente no funciona con jQuery .trigger()o .change(), puede probarlo a continuación usando Chrome 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">

tienes que usar .dispatchEvent()en su 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
fuente
1

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

El changeevento se envía a un elemento cuando su valor cambia. Este evento está limitado a <input>elementos, <textarea>cuadros y <select>elementos. Para cuadros de selección, casillas de verificación y botones de opción, el evento se activa inmediatamente cuando el usuario realiza una selección con el mouse, pero para los otros tipos de elementos, el evento se difiere hasta que el elemento pierde el foco.

Sky Yip
fuente
1

Sé que este es un hilo viejo, pero para otros que buscan, las soluciones anteriores tal vez no sean tan buenas como las siguientes, en lugar de verificar changeeventos, verifique los inputeventos.

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