Método jQuery .live() vs .on() para agregar un evento de clic después de cargar html dinámico
Estoy usando jQuery v.1.7.1 donde el método .live() aparentemente está obsoleto.
El problema que tengo es que cuando cargo dinámicamente html en un elemento usando:
$('#parent').load("http://...");
Si intento agregar un evento de clic después, no registra el evento usando ninguno de estos métodos:
$('#parent').click(function() ...);
o
// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...);
¿Cuál es la forma correcta de lograr esta funcionalidad? Sólo parece funcionar con .live() para mí, pero no debería usar ese método. Tenga en cuenta que #child es un elemento cargado dinámicamente.
Gracias.
Si desea que el controlador de clic funcione para un elemento que se carga dinámicamente, entonces configura el controlador de eventos en un objeto principal (que no se carga dinámicamente) y le asigna un selector que coincida con su objeto dinámico de esta manera:
$('#parent').on("click", "#child", function() {});
El controlador de eventos se adjuntará al #parent
objeto y cada vez que aparezca un evento de clic que se originó en #child
, activará su controlador de clics. Esto se denomina manejo de eventos delegado (el manejo de eventos se delega a un objeto principal).
Se hace de esta manera porque puede adjuntar el evento al #parent
objeto incluso cuando el #child
objeto aún no existe, pero cuando más tarde existe y se hace clic en él, el evento de clic aparecerá en el #parent
objeto, verá que se originó #child
y hay un controlador de eventos para hacer clic #child
y activar su evento.
Prueba esto:
$('#parent').on('click', '#child', function() {
// Code
});
De la $.on()
documentación:
Los controladores de eventos están vinculados únicamente a los elementos seleccionados actualmente; deben existir en la página en el momento en que su código realiza la llamada
.on()
.
Su #child
elemento no existe cuando $.on()
lo invoca, por lo que el evento no está vinculado (a diferencia de $.live()
). #parent
, sin embargo, existe , por lo que vincular el evento a eso está bien.
El segundo argumento en mi código anterior actúa como un 'filtro' que solo se activa si el evento subió #parent
desde #child
.
$(document).on('click', '.selector', function() { /* do stuff */ });
EDITAR: Estoy proporcionando un poco más de información sobre cómo funciona esto, porque... palabras. Con este ejemplo, estará colocando un oyente en todo el documento.
Cuando click
coincide con cualquier elemento .selector
, el evento se propaga al documento principal, siempre y cuando no haya otros oyentes que llamen al event.stopPropagation()
método, lo que superaría la propagación de un evento a los elementos principales.
En lugar de vincularse a un elemento o conjunto de elementos específico, está escuchando cualquier evento proveniente de elementos que coincidan con el selector especificado. Esto significa que puede crear un oyente, una vez, que coincidirá automáticamente con los elementos existentes actualmente, así como con cualquier elemento agregado dinámicamente.
Esto es inteligente por varias razones, incluido el rendimiento y la utilización de la memoria (en aplicaciones a gran escala).
EDITAR:
Obviamente, el elemento principal más cercano que pueda escuchar es mejor, y puede usar cualquier elemento en lugar de él, document
siempre y cuando los elementos secundarios que desee monitorear estén dentro de ese elemento principal... pero eso realmente no tiene nada que ver. con la pregunta.
El equivalente de .live() en 1.7 se ve así:
$(document).on('click', '#child', function() ...);
Básicamente, mire el documento para ver los eventos de clic y filtrelos por #niño.
Sé que es un poco tarde para una respuesta, pero creé un polyfill para el método .live(). Lo probé en jQuery 1.11 y parece funcionar bastante bien. Sé que se supone que debemos implementar el método .on() siempre que sea posible, pero en proyectos grandes, donde no es posible convertir todas las llamadas .live() a llamadas .on() equivalentes por cualquier motivo, lo siguiente podría trabajar:
if(jQuery && !jQuery.fn.live) {
jQuery.fn.live = function(evt, func) {
$('body').on(evt, this.selector, func);
}
}
Simplemente inclúyalo después de cargar jQuery y antes de llamar a live().