Pregunta ¿Enlace de eventos a elementos creados dinámicamente?


Tengo un poco de código donde estoy recorriendo todos los cuadros de selección en una página y vinculando un .hover evento para hacer un poco de twiddling con su ancho en mouse on/off.

Esto sucede en la página preparada y funciona perfectamente.

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

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


1679
2017-10-14 23:25


origen


Respuestas:


A partir de jQuery 1.7 Deberías usar jQuery.fn.on:

$(staticAncestors).on(eventName, dynamicChild, function() {});

Anterior a eso, el enfoque recomendado fue usar live():

$(selector).live( eventName, function(){} );

Sin embargo, live() fue desaprobado en 1.7 a favor de on()y eliminado por completo en 1.9. los live() firma:

$(selector).live( eventName, function(){} );

... puede ser reemplazado con el siguiente on() firma:

$(document).on( eventName, selector, function(){} );

Por ejemplo, si su página crea dinámicamente elementos con el nombre de clase dosomething usted vincularía el evento a un padre que ya existe (este es el meollo del problema aquí, necesitas algo para enlazar, no enlazar al contenido dinámico), esto puede ser (y la opción más fácil) es document. Aunque tenga en cuenta document puede no ser la opción más eficiente.

$(document).on('mouseover mouseout', '.dosomething', function(){
    // what you want to happen when mouseover and mouseout 
    // occurs on elements that match '.dosomething'
});

Cualquier padre que exista en el momento en que el evento esté vinculado está bien. Por ejemplo

$('.buttons').on('click', 'button', function(){
    // do something here
});

se aplicaría a

<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>

1786
2017-08-09 09:51



Hay una buena explicación en la documentación de jQuery.fn.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().

Por lo tanto 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 HTML nuevo en la página, es preferible usar eventos delegados para adjuntar un controlador de eventos, como se describe a continuación.

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 usando código, lo siguiente será manejarlo:

$("#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 conecta un manejador 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 subir de nivel un nivel (desde el clic tr a tbody)

Nota: Los eventos delegados no funcionan SVG.


301
2017-12-09 07:59



Esto es un JavaScript puro solución sin bibliotecas o 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);

dónde 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 se puede implementar como:

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

158
2017-10-14 23:31



Puede agregar eventos a los objetos cuando los crea. Si agrega los mismos eventos a varios 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 */ )
;

59
2017-10-14 23:35



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

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

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

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

40
2018-03-21 22:35



Tratar de usar .live() en lugar de .bind(); el .live() se unirá .hover a su casilla después de que se ejecuta la solicitud Ajax.


37
2017-12-21 07:26



Puede usar el método live () para vincular elementos (incluso los de nueva creación) a eventos y manejadores, como el evento onclick.

Aquí hay un código de muestra que he escrito, donde se puede ver cómo el método live () vincula los elementos elegidos, incluso los de nueva creación, con los eventos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
    </head>

    <body>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>

        <input type="button" id="theButton" value="Click" />
        <script type="text/javascript">
            $(document).ready(function()
                {
                    $('.FOO').live("click", function (){alert("It Works!")});
                    var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
                                                                                                         autoOpen: false,
                                                                                                         tite: 'Basic Dialog'
                                                                                                     });
                    $('#theButton').click(function()
                    {
                        $dialog.dialog('open');
                        return('false');
                    });
                    $('#CUSTOM').click(function(){
                        //$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
                        var button = document.createElement("input");
                        button.setAttribute('class','FOO');
                        button.setAttribute('type','button');
                        button.setAttribute('value','CLICKMEE');
                        $('#container').append(button);
                    });
                    /* $('#FOO').click(function(){
                                                     alert("It Works!");
                                                 }); */
            });
        </script>
    </body>
</html>

21
2018-01-22 01:06



Enlace de eventos en elementos creados dinámicamente

Elemento individual:

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

Elemento hijo:

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

Observe el agregado *. Se desencadenará un evento para todos los niños de ese elemento.

Me he dado cuenta que:

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

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


18
2017-10-07 17:43



Otra solución es agregar el oyente al crear el elemento. En lugar de poner al oyente en el cuerpo, pones al 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");
}

16
2017-11-21 12:01



Prefiero usar el selector y lo aplico en el documento.

Esto se vincula al documento y se aplicará a los elementos que se procesarán después de la carga de la página.

Por ejemplo:

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

16
2018-04-05 07:11



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

A partir de jQuery 1.8, cualquier método de instancia 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>


11
2018-03-26 02:15