jQuery: asociar eventos a elementos HTML creados dinámicamente
30 Dic 2011 por Luis

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>");
});Comentarios
4 comentarios. Comentar.
2. Javier Garcia el 12 Abr 2012 a las 19:10:08
Como saber cual elemento fue el que se cliqueo y activo el evento?
3. Luis el 12 Abr 2012 a las 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.
4. wolfrozen el 03 May 2012 a las 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

1. shabah el 15 Mar 2012 a las 13:48:53
muy muy buen documento