En jQuery, ¿cómo adjuntar eventos a elementos html dinámicos? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Supongamos que tengo algún código jQuery que adjunta un controlador de eventos a todos los elementos con la clase "myclass". Por ejemplo:

$(function(){
    $(".myclass").click( function() {
        // do something
    });
});

Y mi html podría ser el siguiente:

<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>

Eso funciona sin ningún problema. Sin embargo, considere si el elementos de "myclass" fueron escritos en la página en algún momento futuro.

Por ejemplo:

<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
    $("#anchor1").click( function() {
        $("#anchor1").append('<a class="myclass" href="#">test4</a>');
    });
});
</script>

En este caso, el enlace "test4" se crea cuando un usuario hace clic en un#anchor1.

El enlace "test4" no tiene asociado el manejador click (), aunque tenga class="myclass".

¿Alguna idea de cómo puedo arreglar esto?

Básicamente, me gustaría escribir el manejador click() una vez y hacer que se aplique tanto al contenido presente en la carga de la página como al contenido traído más tarde a través de Ajax / DHTML.

Author: frankadelic, 2009-08-31

8 answers

Estoy agregando una nueva respuesta para reflejar los cambios en versiones posteriores de jQuery. El .el método live () está obsoleto a partir de jQuery 1.7.

De http://api.jquery.com/live/

A partir de jQuery 1.7, el .el método live () está obsoleto. Utilizar .on () para adjuntar controladores de eventos. Los usuarios de versiones anteriores de jQuery deben usar .delegate() con preferencia a .vivir().

Para jQuery 1.7+ puede adjuntar un controlador de eventos a un elemento padre usando .on (), y pasar el selector a combinado con 'myclass' como argumento.

Véase http://api.jquery.com/on /

Así que en lugar de...

$(".myclass").click( function() {
    // do something
});

Puedes escribir...

$('body').on('click', 'a.myclass', function() {
    // do something
});

Esto funcionará para todas las etiquetas a con 'myclass' en el cuerpo, ya sea que ya estén presentes o que se agreguen dinámicamente más tarde.

La etiqueta body se usa aquí ya que el ejemplo no tenía ninguna etiqueta estática circundante más cercana, sino cualquier etiqueta padre que exista cuando la .on method call occurs funcionará. Por ejemplo, una etiqueta ul para una lista que tendrá los elementos dinámicos agregados se verían así:

$('ul').on('click', 'li', function() {
    alert( $(this).text() );
});

Mientras exista la etiqueta ul, esto funcionará (todavía no es necesario que existan elementos li).

 782
Author: Sean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-08 12:36:10

A veces hacer esto (la respuesta más votada) no siempre es suficiente:

$('body').on('click', 'a.myclass', function() {
    // do something
});

Esto puede ser un problema debido al orden en que se disparan los controladores de eventos. Si te encuentras haciendo esto, pero está causando problemas debido al orden en el que se maneja.. Siempre puede envolver eso en una función, que cuando se llama "refresca" el oyente.

Por ejemplo:

function RefreshSomeEventListener() {
    // Remove handler from existing elements
    $("#wrapper .specific-selector").off(); 

    // Re-add event handler for all matching elements
    $("#wrapper .specific-selector").on("click", function() {
        // Handle event.
    }
}

Debido a que es una función, cada vez que configure mi oyente de esta manera, normalmente lo llamo en el documento listo:

$(document).ready(function() {
    // Other ready commands / code

    // Call our function to setup initial listening
    RefreshSomeEventListener();
});

Luego, cada vez que agregue algún elemento agregado dinámicamente, llame a ese método nuevamente:

function SomeMethodThatAddsElement() {
    // Some code / AJAX / whatever.. Adding element dynamically

    // Refresh our listener, so the new element is taken into account
    RefreshSomeEventListener();
}

Esperemos que esto ayude!

Saludos,

 65
Author: Chandler Zwolle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-18 13:29:33

Después de jQuery 1.7 los métodos preferidos son .el () y .off()

La respuesta de Sean muestra un ejemplo.

Ahora en desuso:

Utilice las funciones de jQuery.live() y .die(). Disponible en jQuery 1.3.x

De los documentos:

Para mostrar el texto de cada párrafo en un cuadro de alerta cada vez que se hace clic:

$("p").live("click", function(){
  alert( $(this).text() );
});

Además, el plugin livequery hace esto y tiene soporte para más eventos.

 36
Author: Matt Brunell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:51

Si está agregando una pila de anclas al DOM, busque en la delegación de eventos en su lugar.

Este es un ejemplo sencillo:

$('#somecontainer').click(function(e) {   
  var $target = $(e.target);   
  if ($target.hasClass("myclass")) {
    // do something
  }
});
 5
Author: ScottE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-19 18:05:12

Vincula un controlador a un evento (como clic) para todos los elementos coincidentes actuales y futuros. También puede enlazar eventos personalizados.

Link text

$(function(){
    $(".myclass").live("click", function() {
        // do something
    });
});
 3
Author: andres descalzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-31 19:32:46

Puede enlazar un evento de un solo clic a una página para todos los elementos, sin importar si ya están en esa página o si llegarán en algún momento futuro, así:

$(document).bind('click', function (e) {
   var target = $(e.target);
   if (target.is('.myclass')) {
      e.preventDefault(); // if you want to cancel the event flow
      // do something
   } else if (target.is('.myotherclass')) {
      e.preventDefault();
      // do something else
   }
});

Lo he estado usando por un tiempo. Funciona como un encanto.

En jQuery 1.7 y versiones posteriores, se recomienda usar .on() en lugar de bind o cualquier otro método de delegación de eventos, pero .bind() todavía funciona.

 2
Author: i--,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-29 15:15:42

Si está en jQuery 1.3+ entonces use . en vivo()

Enlaza un controlador a un evento (como click) para todos los actuales y futuros - elemento coincidente. También puede enlazar personalizado evento.

 1
Author: redsquare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-31 19:31:26

Desea utilizar la función live(). Véase los documentos.

Por ejemplo:

$("#anchor1").live("click", function() {
    $("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
 1
Author: Adam Bellaire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-31 19:31:52