javascript obtiene ¿Enlace de eventos en elementos creados dinámicamente?




jquery asignar evento dinamicamente (19)

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.


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>


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)


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"))

<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>

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.


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() .


Enlace el evento a un padre que ya existe:

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

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");
}

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);
}

Tome nota de la clase "PRINCIPAL" en que se coloca el elemento, por ejemplo,

<div class="container">
     <ul class="select">
         <li> First</li>
         <li>Second</li>
    </ul>
</div>

En el escenario anterior, el objeto PRINCIPAL que observará jQuery es "contenedor".

Luego, básicamente, tendrá nombres de elementos debajo del contenedor, como ul , li , y select :

$(document).ready(function(e) {
    $('.container').on( 'click',".select", function(e) {
        alert("CLICKED");
    });
 });

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


Intenta así ...

$(document).on( 'click', '.click-activity', function () { ... });

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 .


Estaba buscando una solución para que $.bind y $.unbind funcionen sin problemas en elementos agregados dinámicamente.

Como on() hace el truco para adjuntar eventos, para crear un desvinculación falsa en aquellos a los que llegué:

const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );

// unbind the click
$('body').on('click', 'button.send', function(){} );

Prefiero que los oyentes de eventos se implementen de una manera modular en lugar de hacer scripts a un oyente de eventos a nivel de document . Por lo tanto, me gusta a continuación. Tenga en cuenta que no puede sobrescribir un elemento con el mismo detector de eventos, así que no se preocupe por adjuntar un escucha más de una vez, solo una pega.

var iterations = 4;
var button;
var body = document.querySelector("body");

for (var i = 0; i < iterations; i++) {
    button = document.createElement("button");
    button.classList.add("my-button");
    button.appendChild(document.createTextNode(i));
    button.addEventListener("click", myButtonWasClicked);
    body.appendChild(button);
}

function myButtonWasClicked(e) {
    console.log(e.target); //access to this specific button
}


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>


Cualquier declaración que exista en el momento en que el evento esté vinculado y si su página estaba creando elementos dinámicamente con el botón de nombre de clase, vincularía el evento a un padre que ya existe

$(document).ready(function(){
  //Particular Parent chield click
  $(".buttons").on("click","button",function(){
    alert("Clicked");
  });  
  
  //Dynamic event bind on button class  
  $(document).on("click",".button",function(){
    alert("Dymamic Clicked");
  });
  $("input").addClass("button");  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="buttons">
  <input type="button" value="1">
  <button>2</button>
  <input type="text">
  <button>3</button>  
  <input type="button" value="5">  
  </div>
<button>6</button>


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
});

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





unobtrusive-javascript