Ardilla Quio Ardilla Quio

30 de Diciembre de 2011

jQuery: asociar eventos a elementos HTML creados dinámicamente

Para asociar eventos a elementos HTML con jQuery basta con usar bind() (o cualquiera de sus variantes) en el elemento y, cuando se cargue el código javascript, el evento quedará asociado. El problema viene dado cuando el elemento al que queremos asociar un evento no existe en el momento de cargar el javascript, sino que será creado dinámicamente en algún momento. Hasta que el elemento exista, no se le pueden asociar eventos. En este artículo veremos cómo podemos solucionar este problema con la función on() de jQuery.

Asociando eventos con bind

Para ilustrar el caso, voy a poner un ejemplo de lo que podríamos esperar que funcionase. Supongamos que tenemos este HTML:

<div id="blog-test-cont">
	<p class="blog-test">Pulsa para probar</p>
</div>

El código javascript sería este:

var bt_count = 0;
$("#blog-test-cont .blog-test").bind("click", function(){
	$(this).after("<p class=\"blog-test\">Pulsa para probar " + (++bt_count) + "</p>");
});

En este caso, como asociamos el evento a todos los elementos que tienen la clase blog-test, podríamos pensar que este evento se asociaría a todos los elementos que se crean dinámicamente con esa clase. Vamos a comprobar que sólo el elemento creado de antemano tiene este comportamiento:

Pulsa para probar

Esto se debe a que cuando se ejecuta el javascript, éste recorre el DOM y asocia el evento a todos los elementos que existen en ese momento que tengan la clase blog-test (descendientes del elemento blog-test-cont). Cuando se crean los elementos de forma dinámica, el javascript ya se ha ejecutado y, por lo tanto, los elementos creados después no tienen asociado el evento.

Asociando eventos con on

Este código sólo es válido para jQuery 1.7 o superior. Para versiones anteriores puede usarse delegate() (versión 1.4.3 o superior) o live(). En el último apartado veremos el mismo código con estas dos funciones.

Para que el código funcione como nosotros esperamos, en lugar de usar bind(), debemos usar on(), de esta forma:

var bt_count = 0;
$("#blog-test-cont").on("click", ".blog-test", function(){
	$(this).after("<p class=\"blog-test\">Pulsa para probar " + (++bt_count) + "</p>");
});

Veamos cómo funciona ahora:

Pulsa para probar

Podemos comprobar que ahora todos los elementos creados dinámicamente tienen el mismo comportamiento que el creado de antemano.

Esto se debe a que la función on() no asocia el evento a los elementos con clase blog-test, como hace bind(), sino que asocia el código al elemento blog-test-cont de forma que cuando el evento se dispara y se propaga por el DOM, ascendiendo hasta éste, comprueba si el elemento objetivo tiene clase blog-test y, en caso afirmativo, dispara el evento sobre él. De esta forma, no importa en qué momento se haya creado el elemento objetivo, ya que la comprobación se hace siempre que se ejecuta la acción.

Versiones anteriores de jQuery

El mismo código para versiones de jQuery menores que 1.7 y mayores o iguales a 1.4.3:

var bt_count = 0;
$("#blog-test-cont").delegate(".blog-test", "click", function(){
	$(this).after("<p class=\"blog-test\">Pulsa para probar " + (++bt_count) + "</p>");
});

El mismo código para versiones de jQuery menores que 1.4.3 y mayores o iguales a 1.3:

var bt_count = 0;
$("#blog-test-cont .blog-test").live("click", function(){
	$(this).after("<p class=\"blog-test\">Pulsa para probar " + (++bt_count) + "</p>");
});

59 comentarios

Oscar David Díaz Fortaleché

11/02/2015 16:23:28

Gracias, estaba como loco buscando algo que me resolviera ese pequeño problema.

Iván

03/02/2015 01:25:47

Muchas gracias por el aporte!!! Llevaba días loco tratando de solucionar esto...

Francisco Rosales

22/01/2015 05:43:10

Tengo un div que muestra contenido input text (al dar click sale un calendario) traido vía AJAX:

<div id="contenido_traido_con_ajax">

<input type="text" class="claseX" value="calendario " />

</div>

Afuera de ese div, tengo otro input text con la misma clase:

<input type="text" class="claseX" value="calendario " />

En un javascript externo tengo las funciones que se activan al hacer

click en el input text con la class=claseX

El problema es, el input que no fue traido vía ajax funciona

perfectamente, en cambio el que sí fue traido con ajax no funciona.

Estuve googleando y al parecer es un problema muy común, e intenté

copiar una función que en teoría es como que "recarga" el javascript

para "que se de cuenta que hay html nuevo" según entendí, pero la

verdad no lo logro hacer andar.

¿Alguien tiene experiencia con un problema así?

Saludos!

Samo

07/01/2015 16:38:44

Gracias, me ha servido mucho, estoy en un nuevo empleo como programador y me salvo en una nueva tarea que realizo.

franco

04/12/2014 20:58:41

Genio! Muchas gracias! Una vez lo necesitaba y de vago no lo busque! Muy bien explicado! Gracias nuevamente!

Franklin Ruiz

03/09/2014 23:23:51

Me has aclarado una duda que tenía desde hace años, no sabes cuantas líneas de código me has ahorrado. Gracias sinceras!

rtyrtyrty

15/07/2014 19:37:20

gracias me sirvio para el boton q se genera automaticamente hasta q se hace la consulta. Batalle mucho para asociarle el evento de click al bton que se crea automaticamente

MASTER

01/07/2014 17:16:00

Hola que tal he andado buscando como dare estilo a elementos dinamicos, ya que tengo un problemon esto se puede aplicar a Tab? bueno el codigo se ve sencillotendre que hacer prubas y comento

Saludos =)

@elkangri23

16/06/2014 16:29:03

Mil gracias por el aporte, bastante rallado estaba con el tema, siendo principiante en jquery

Ruth

27/05/2014 23:44:29

Muy claro, felicitaciones!

Una gran ayuda para los que empezamos con Jquery

fernando

17/05/2014 17:58:55

Muchas gracias por compartir este trabajo, me soluciono el problema y fue un placer leer como se explica aqui.Gracias de nuevo

Marco

14/02/2014 06:48:18

Muchisimas gracias viejo , estaba buscando una respuesta como esta.

Respecto a la pregunta que realizo javier Garcia , puedes obtener el id del elemnto que invoco el evento con la siguiente sentencia $(this).attr("id")

Carlos

12/11/2013 05:59:04

gracias me ayudaste a resolver un problema que tenia, jaja

llevaba mas de dos días tratando de resolver este problema¡¡¡¡

Luciano

05/10/2013 22:49:33

Solucionado gracias:

Al parecer al on se le puede enviar una configuracion con los eventos

$('#tabla').on({

click : function() {…},

mouseenter: function() {…},

mouseleave: function() {…}

}, 'a.borrar');

Luciano

05/10/2013 22:32:09

Muchas gracias, existe alguna forma de hacer lo mismo pero con el evento hover ?

Cesar

01/10/2013 03:37:07

muy bueno, gracias

Anónimo

06/09/2013 06:15:55

Excelente!!! Gracias!

jlnegrito

03/07/2013 21:39:10

Gracias, una gran ayuda. Estaba creando <li> dinámicamente dentro de <ul> y no funcaba.

La solución: $('ul').on('click','li',function(){}

Rodolfo

26/06/2013 13:57:04

Espectacular documento. He leído 40.000 otros y no me han ayudado a resolver el problema como lo ha hecho este. Muchísimas gracias por esta aportación. Por cierto, la página, preciosa!

Suso

15/06/2013 15:56:34

fantástico post!!!. Voy a ponerlo en práctica

DSK25

31/03/2013 03:23:59

Gracias me sirvio. Sabe como puedo eliminar divs creados dinamicamente?

ariel

08/03/2013 04:36:27

gracias.. me la pase renegando muchas veces por este problemita... muchas graciass!!!!!

Ch

24/01/2013 12:06:59

Gracias. Buena expliación.

Javier Garcia

23/10/2012 18:22:45

Loco, muy claro muchas gracias se me olvidaba lo del DOM en los elementos dinamicos y no encontraba el script donde lo hice jejeje, GRACIAS!

Richard Omar

19/09/2012 07:08:44

Gracias!! Muy bueno!!

wolfrozen

03/05/2012 00:00:39

Hola solo quería darte las gracias por tu explicación, que me fue muy útil para un proyecto que estoy realizando

Luis

12/04/2012 19:53:01

Hola Javier.

El elemento que ha activado el evento se referencia dentro de la función que utilizas como $(this).

Si miras el código de ejemplo, lo que hace la función es añadir un nuevo párrafo justo después de aquel en el que se ha hecho click con $(this).after().

Un saludo.

Javier Garcia

12/04/2012 19:10:08

Como saber cual elemento fue el que se cliqueo y activo el evento?

shabah

15/03/2012 13:48:53

muy muy buen documento

Comentario anónimo
Comentar como usuario