javascript - obtiene - jquery asignar evento dinamicamente




¿Enlace de eventos en elementos creados dinámicamente? (16)

Tengo un poco de código en el que hago un bucle a través de todos los cuadros de selección en una página y los .hover un evento .hover para hacer un poco de maniobra con su ancho en el mouse on/off .

Esto sucede en la página lista y funciona bien.

El problema que tengo es que los cuadros de selección que agregué a través de Ajax o DOM después del bucle inicial no tendrán el evento enlazado.

He encontrado este complemento ( jQuery Live Query Plugin ), pero antes de agregar otros 5k a mis páginas con un complemento, quiero ver si alguien sabe una forma de hacerlo, ya sea directamente con jQuery o por otra opción.


Enlace de eventos en elementos creados dinámicamente

Elemento único:

$(document.body).on('click','.element', function(e) {  });

Elemento hijo:

 $(document.body).on('click','.element *', function(e) {  });

Note el agregado * . Se activará un evento para todos los hijos de ese elemento.

Me he dado cuenta que:

$(document.body).on('click','.#element_id > element', function(e) {  });

Ya no funciona, pero funcionaba antes. He estado usando jQuery de Google CDN , pero no sé si lo cambiaron.


Aquí es por qué los elementos creados dinámicamente no responden a los clics:

var body = $("body");
var btns = $("button");
var btnB = $("<button>B</button>");
// `<button>B</button>` is not yet in the document.
// Thus, `$("button")` gives `[<button>A</button>]`.
// Only `<button>A</button>` gets a click listener.
btns.on("click", function () {
  console.log(this);
});
// Too late for `<button>B</button>`...
body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

Como solución alternativa, debe escuchar todos los clics y verificar el elemento de origen:

var body = $("body");
var btnB = $("<button>B</button>");
var btnC = $("<button>C</button>");
// Listen to all clicks and
// check if the source element
// is a `<button></button>`.
body.on("click", function (ev) {
  if ($(ev.target).is("button")) {
    console.log(ev.target);
  }
});
// Now you can add any number
// of `<button></button>`.
body.append(btnB);
body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

Esto se llama "Delegación de eventos". Buenas noticias, es una característica incorporada en jQuery :-)

var i = 11;
var body = $("body");
body.on("click", "button", function () {
  var letter = (i++).toString(36).toUpperCase();
  body.append($("<button>" + letter + "</button>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>


Enlace el evento a un padre que ya existe:

$(document).on("click", "selector", function() {
    // Your code here
});

Esta es una solución de JavaScript pura sin bibliotecas ni complementos:

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);

donde hasClass es

function hasClass(elem, className) {
    return elem.className.split(' ').indexOf(className) > -1;
}

Demo en vivo

El crédito es para Dave y Sime Vidas.

Usando JS más moderno, hasClass puede implementarse como:

function hasClass(elem, className) {
    return elem.classList.contains(className);
}

Esto se hace por delegación de eventos. El evento se enlazará en el elemento de la clase contenedora, pero se delegará en el elemento de la clase selectora. Así es como funciona.

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});

Nota:

El elemento clase envoltura puede ser cualquier cosa, por ejemplo. Documento, cuerpo o envoltorio. La envoltura ya debería existir.


Hay una buena explicación en la documentación de on() .

En breve:

Los controladores de eventos están vinculados solo a los elementos seleccionados actualmente; deben existir en la página en el momento en que su código realiza la llamada a .on() .

Así, en el siguiente ejemplo, #dataTable tbody tr debe existir antes de que se genere el código.

$("#dataTable tbody tr").on("click", function(event){
    console.log($(this).text());
});

Si se está inyectando nuevo HTML en la página, es preferible usar eventos delegados para adjuntar un controlador de eventos, como se describe a continuación.

Los eventos delegados tienen la ventaja de que pueden procesar eventos de elementos descendientes que se agregan al documento en un momento posterior. Por ejemplo, si la tabla existe, pero las filas se agregan dinámicamente utilizando el código, lo siguiente lo manejará:

$("#dataTable tbody").on("click", "tr", function(event){
    console.log($(this).text());
});

Además de su capacidad para manejar eventos en elementos descendientes que aún no se han creado, otra ventaja de los eventos delegados es su potencial para una sobrecarga mucho menor cuando se deben monitorear muchos elementos. En una tabla de datos con 1,000 filas en su tbody , el primer ejemplo de código adjunta un controlador a 1,000 elementos.

Un enfoque de eventos delegados (el segundo ejemplo de código) adjunta un controlador de eventos a un solo elemento, el tbody , y el evento solo necesita aumentar un nivel (desde el tr click hasta el tbody ).

Nota: Los eventos delegados no funcionan para SVG .


Intente usar .live() lugar de .bind() ; el .live() .hover a su casilla de verificación después de que se ejecute la solicitud Ajax.


Otra solución es agregar el oyente al crear el elemento. En lugar de poner al oyente en el cuerpo, pones el oyente en el elemento en el momento en que lo creas:

var myElement = $('<button/>', {
    text: 'Go to Google!'
});

myElement.bind( 'click', goToGoogle);
myElement.append('body');


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}

Prefiero usar el selector y lo aplico en el documento.

Esto se enlaza con el documento y se aplicará a los elementos que se representarán después de cargar la página.

Por ejemplo:

$(document).on("click", $(selector), function() {
    // Your code here
});

Puede adjuntar evento a elemento cuando se crea dinámicamente usando jQuery(html, attributes) .

A partir de jQuery 1.8 , cualquier método de instancia de jQuery (un método de jQuery.fn ) se puede usar como una propiedad del objeto pasado al segundo parámetro:

function handleDynamicElementEvent(event) {
  console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<select>", {
    html: $.map(Array(3), function(_, index) {
      return new Option(index, index)
    }),
    on: {
      change: handleDynamicElementEvent
    }
  })
  .appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>


Puedes agregar eventos a los objetos cuando los creas. Si está agregando los mismos eventos a múltiples objetos en diferentes momentos, la creación de una función con nombre podría ser el camino a seguir.

var mouseOverHandler = function() {
    // Do stuff
};
var mouseOutHandler = function () {
    // Do stuff
};

$(function() {
    // On the document load, apply to existing elements
    $('select').hover(mouseOverHandler, mouseOutHandler);
});

// This next part would be in the callback from your Ajax call
$("<select></select>")
    .append( /* Your <option>s */ )
    .hover(mouseOverHandler, mouseOutHandler)
    .appendTo( /* Wherever you need the select box */ )
;

Simplemente podría ajustar su llamada de enlace de evento en una función y luego invocarla dos veces: una vez en el documento listo y una vez después de su evento que agrega los nuevos elementos DOM. Si lo hace, querrá evitar vincular el mismo evento dos veces en los elementos existentes, por lo que necesitará desvincular los eventos existentes o (mejor) vincular solo a los elementos DOM que se crean recientemente. El código se vería algo así:

function addCallbacks(eles){
    eles.hover(function(){alert("gotcha!")});
}

$(document).ready(function(){
    addCallbacks($(".myEles"))
});

// ... add elements ...
addCallbacks($(".myNewElements"))

Utilice el método .on() de jQuery on() para adjuntar controladores de eventos al elemento vivo.

También a partir de la versión 1.9 se .live() método .live() .


podrías usar

$('.buttons').on('click', 'button', function(){
    // your magic goes here
});

o

$('.buttons').delegate('button', 'click', function() {
    // your magic goes here
});

Estos dos métodos son equivalentes pero tienen un orden diferente de parámetros.

ver: jQuery Delegate Event


Solución más flexible para crear elementos y eventos de enlace ( source )

// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});

//creating a dynamic button
 var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });

// binding the event
 $btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
    console.log('clicked');
 });

// append dynamic button to the dynamic container
$div.append($btn);

// add the dynamically created element(s) to a static element
$("#box").append($div);

Nota: Esto creará una instancia de controlador de eventos para cada elemento (puede afectar el rendimiento cuando se usa en bucles)


<html>
    <head>
        <title>HTML Document</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    </head>

    <body>
        <div id="hover-id">
            Hello World
        </div>

        <script>
            jQuery(document).ready(function($){
                $(document).on('mouseover', '#hover-id', function(){
                    $(this).css('color','yellowgreen');
                });

                $(document).on('mouseout', '#hover-id', function(){
                    $(this).css('color','black');
                });
            });
        </script>
    </body>
</html>




unobtrusive-javascript