Si te interesa saber más sobre eventos en JQuery puedes leer el desarrollo completo, con fallos y aciertos que explico a continuación, pero si quieres ir directo al grano y ver como se soluciona de forma elegante puedes ir al final del artículo directamente.
En principio parece sencillo.
<a href="#" id="nuevoBoton">Añadir botón</a> <div id="contenedor"> <a class="boton" data-val="1" href="#">Pulsa</a> </div> <script> $("a.boton").on('click', function() { alert('El valor es: ' + $(this).data('val')); }); $("#nuevoBoton").on('click',function() { var boton = '<a href="#" class="boton" data-val="' + parseInt(Math.random()*10) + '">Pulsa</a>'; $('#contenedor').append(boton); }); </script>
¿Qué ocurre?
Si hacemos click en el primer botón todo funciona correctamente. Pero cuando añadimos botones nuevos, en estos no se ejecuta el evento. Esto se debe a que hemos vinculado al selector a.boton al cargar la página, por lo tanto los botones que añadimos dinámicamente no tienen este evento vinculado.
De acuerdo, esto tiene fácil solución, cada vez que añada un botón tengo que vincular el evento click:
<script> $("a.boton").on('click', function() { alert('El valor es: ' + $(this).data('val')); }); $("#nuevoBoton").on('click',function() { var boton = '<a href="#" class="boton" data-val="' + parseInt(Math.random()*10) + '">Pulsa</a>'; $('#contenedor').append(boton); $("a.boton").on('click', function() { alert('El valor es: ' + $(this).data('val')); }); }); </script>
Ahora los botones que añadimos ejecutan muestran el 'alert', pero cada vez que añadimos un botón, estamos vinculando el evento a todos los elementos del DOM que coinciden con el selector, por lo que en el caso del primer botón, el evento se lanzará tantas veces como nuevos botones hayamos añadido.
¿Cómo lo solucionamos?
Sencillo, desvinculamos todos los eventos antes de añadir los nuevos usando el método .off de Jquery:
<script> $("a.boton").on('click', function() { alert('El valor es: ' + $(this).data('val')); }) $("#nuevoBoton").on('click',function() { var boton = '<a href="#" class="boton" data-val="' + parseInt(Math.random()*10) + '">Pulsa</a>'; $('#contenedor').append(boton); $("a.boton").off('click'); $("a.boton").on('click', function() { alert('El valor es: ' + $(this).data('val')); }); }); </script>
Y ahora sí conseguimos el resultado deseado. Solo salta una vez el mensaje por cada vez que pulsamos el botón. No obstante hacerlo de esta forma sobrecarga el navegador, pues estamos vinculando y desvinculando todos los eventos para cada nuevo botón que añadimos, que pueden llegar a ser muchos. Pero vamos a ver que se puede hacer de una forma más elegante y eficiente:
Añadir eventos a elementos creados de forma dinámica de forma elegante
En este caso vamos a hacer uso de lo que en Jquery se llaman delegados. Esto nos permite vincular eventos a un selector de manera que cada vez que se añadan nuevos elementos, se vincule automáticamente el evento:
<script> $("#nuevoBoton").on('click',function() { var boton = '<a href="#" class="boton" data-val="' + parseInt(Math.random()*10) + '">Pulsa</a>'; $('#contenedor').append(boton); }); $("#contenedor").on('click','a.boton', function() { alert('El valor es: ' + $(this).data('val')); }) </script>
El evento se vincula al contenedor, pero se delega en los botones. De esta forma cuando añadamos nuevos elementos automáticamente se vincularán sus eventos correspondientes.
Para terminar os añado un jsfiddle para que podáis probar el resultado final:
http://jsfiddle.net/cvdta/
Muy buen aporte, me sacaste de un aprieto, GRACIAS :D
ResponderEliminarGracias! Genial! Muy Bien comentado!
ResponderEliminar(Y) Súper! me ayudo!!! Gracias!
ResponderEliminarBuenas tardes una pregunta,suponiendo que el boton que se crea dinamicamente al clickearlo ejecuta una peticion ajax, tengo que declarar dentro del clousure nuevamente la peticion.
ResponderEliminarsi me hago entender?
Hola Ricardo, entiendo que creas el botón con una petición ajax inicial, y luego lo bindead a una acción que hace otra petición ajax. Lo apropiado es que utilices un método público dentro del closure al que bindearas en el click del botón. Recuerda que para hacer un método público en el closure tienes que ponerlo dentro del return. Si aún tienes dudas envíame un jdfiddle con el código y así seguro que es mas fácil de ver, un saludo:)
EliminarQue tal, tengo un formulario con select dependientes
ResponderEliminarZona, Municipio, Localidad
Puedo crear los selects, pero de que manera podria asignarle las funciones o eventos
para llenarlos