> Manuales > Manual de jQuery

Los delegated events de jQuery permiten asociar comportamientos a elementos que aún no se encuentran en la página, usando el mismo método on(), aunque definiendo el selector donde quieres estos eventos delegados.

Antes de jQuery 1.7 utilizábamos live() para poder definir eventos con respecto a un selector y que el sistema estuviera pendiente sobre si aparecían nuevos elementos respondiendo a ese selector en la página, a los que le asignaría el evento automáticamente.

Desde hace tiempo se han simplificado las cosas y como sabemos, la librería ha dejado obsoletas varias funciones de eventos y concentrado su uso en el método "on()". En este artículo veremos un uso útil, nada difícil, pero que a veces es desconocido y provoca dudas.

¿Por qué eventos delegados (delegated events)?

Veamos para qué sirven los delegated events de una manera sencilla, por medio de un caso práctico. Surge de una duda que tenía nuestro compañero Chris:

Tengo un problemilla con jQuery: voy agregando elementos a una página, insertando divs. A cada elemento agregado le pongo una etiqueta A por si lo quieren borrar, pero el evento "click" que asigno a los enlaces no se agrega dinámicamente. No reconoce el clic, o sea, no pasa nada.

Dicho de otro modo, Chris inyecta código en la página. Los elementos que inyecta deberían responder a eventos. Pero los eventos definidos no funcionan, porque su creación es anterior a la existencia de esos elementos, es decir, definió el evento "click" previamente a la inyección del elemento sobre el que se tenía que asignar ese evento.

La solución bruta es la siguiente:
Cuando inyectes un código, si hay elementos que quieras que respondan a eventos, genera esos comportamientos de respuesta a los eventos, justo después de haberlos inyectado. O sea, después de hacer el "append()", haces el "on()" sobre los elementos que acabas de insertar que quieras que respondan a eventos.

Esta solución no es del todo bonita, porque tienes que estar siempre pendiente de qué se inserta en la página, para ver si le tienes que asignar eventos. Sobre todo en esquemas de páginas altamente dinámicas, donde se inyecta HTML desde varios lugares de tu Javascript, puede ser un jaleo.

La solución elegante son los eventos delegated:
Lo que querrás hacer es definir tus eventos una vez, quizás en el "document ready", y que esta definición afecte a todos los elementos existentes actualmente y a los que se puedan inyectar en el futuro, ¿no?

Afortunadamente es bien fácil.

Cómo hacer un delegated event

El mecanismo es bien simple, lo verás con un ejemplo. Tienes un código como este:

<div id="productos">
<div class="prod">
Producto predeterminado
<br>
<a href="#" class="cerrarprod">cerrar</a>
</div>
</div>

En la mayoría de los casos, si quieres que el producto se borre al pulsar sobre el enlace "cerrar", quizás defines un evento así:

$(".cerrarprod").on("click", function(e){
e.preventDefault()?
$(this).parent().remove()?
})?

Eso funcionará perfectamente, sobre todos los enlaces de la class="cerrarprod" que actualmente haya en el documento HTML. El problema es que luego inyectes otros productos:

$("#productos").append('<div class="prod">' + nombreProd + '<br><a href="#" class="cerrarprod">cerrar</a></div>')

Nota: Inyectar código de esa manera no es muy "elegante". Si quieres hacerte un favor a ti mismo, trata de usar algún sistema de plantillas Javascript.

Esos nuevos productos tienen el enlace de "cerrar", pero lamentablemente no funcionará tu evento.

En lugar de definir el evento de la anterior manera, echa un vistazo al código siguiente.

$("#productos").on("click", "a.cerrarprod", function(e){
e.preventDefault()?
$(this).parent().remove()?
})?

Este sería el método correcto de usar estos eventos delegados. Lo analizamos:

Es así de simple. De este modo consigues que cualquier enlace en la división id="productos" que pueda tener la clase "cerrarprod" y que exista en el momento actual o en cualquier momento futuro, tenga asignado ese comportamiento de evento.

Conclusión

Yo lo veo superclaro. En vez de asignar el evento a elementos que realmente no sabes si están todos en la página, porque más adelante puedan ser añadidos con métodos de jQuery como "append()", "appendTo()", "prepend()" o similares, lo asignas a un elemento que sí existe (podría ser incluso el propio "document"). Luego le indicas como parámetro en el método "on()" el selector donde realmente quieres que esos eventos estén asignados ahora y en elementos futuros que pueda haber.

¡Pruébalo! ¿lo has conseguido? publica tu código como comentario y ayuda a los demás.

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online Escu...

Manual