¿Cómo adjunto eventos a elementos HTML dinámicos con jQuery? [duplicar]
Supongamos que tengo algún código jQuery que adjunta un controlador de eventos a todos los elementos con 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 problema. Sin embargo, considere si los .myclass
elementos se escribieron 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 test4
enlace se crea cuando un usuario hace clic en a#anchor1
.
El test4
enlace no tiene el click()
controlador asociado, aunque sí lo tiene class="myclass"
.
Básicamente, me gustaría escribir el click()
controlador una vez y que se aplique tanto al contenido presente al cargar la página como al contenido incorporado más tarde a través de AJAX/DHTML . ¿Alguna idea de cómo puedo solucionar este problema?
Estoy agregando una nueva respuesta para reflejar los cambios en versiones posteriores de jQuery. El método .live() está obsoleto a partir de jQuery 1.7.
Desde http://api.jquery.com/live/
A partir de jQuery 1.7, el método .live() está en desuso. Utilice .on() para adjuntar controladores de eventos. Los usuarios de versiones anteriores de jQuery deberían utilizar .delegate() en lugar de .live().
Para jQuery 1.7+, puede adjuntar un controlador de eventos a un elemento principal usando .on() y pasar un selector combinado con 'myclass' como argumento.
Ver http://api.jquery.com/on/
Entonces en lugar de...
$(".myclass").click( function() {
// do something
});
Puedes escribir...
$('body').on('click', 'a.myclass', function() {
// do something
});
Esto funcionará para todas las etiquetas con 'miclase' en el cuerpo, ya sea que ya estén presentes o que se agreguen dinámicamente más adelante.
La etiqueta del cuerpo se utiliza aquí ya que el ejemplo no tenía una etiqueta circundante estática más cercana, pero cualquier etiqueta principal que exista cuando se produce la llamada al método .on funcionará. Por ejemplo, una etiqueta ul para una lista a la que se agregarán elementos dinámicos se vería así:
$('ul').on('click', 'li', function() {
alert( $(this).text() );
});
Mientras exista la etiqueta ul, esto funcionará (aún no es necesario que existan elementos li).
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 activan los controladores de eventos. Si se encuentra haciendo esto, pero está causando problemas debido al orden en que se maneja... Siempre puede incluirlo en una función, que cuando se llama "actualiza" 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 configuro mi oyente de esta manera, normalmente lo invoco cuando el documento está 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();
}
¡Ojalá esto ayude!
Saludos,
Después de jQuery 1.7 los métodos preferidos son .on() y .off()
La respuesta de Sean muestra un ejemplo.
Ahora en desuso:
Utilice las funciones jQuery
.live()
y.die()
. Disponible en jQuery 1.3.xDe los documentos:
Para mostrar el texto de cada párrafo en un cuadro de alerta cada vez que se hace clic en él:
$("p").live("click", function(){ alert( $(this).text() ); });
Además, el complemento livequery hace esto y admite más eventos.
Si está agregando un montón de anclajes al DOM, busque la delegación de eventos.
He aquí un ejemplo sencillo:
$('#somecontainer').click(function(e) {
var $target = $(e.target);
if ($target.hasClass("myclass")) {
// do something
}
});
Puedes vincular 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 de maravilla.
En jQuery 1.7 y posteriores, se recomienda usarlo .on()
en lugar de vincular o cualquier otro método de delegación de eventos, pero .bind()
aún funciona.