javascript created - La liaison d'événement sur les éléments créés dynamiquement?




added to (17)

J'ai un peu de code où je suis en boucle à travers toutes les boîtes de sélection sur une page et de lier un événement .hover à eux pour faire un peu de twiddling avec leur largeur à la mouse on/off .

Cela arrive à la page prête et fonctionne très bien.

Le problème que j'ai est que toutes les boîtes de sélection que j'ajoute via Ajax ou DOM après la boucle initiale n'auront pas l'événement lié.

J'ai trouvé ce plugin ( jQuery Live Query Plugin ), mais avant d'ajouter 5k à mes pages avec un plugin, je veux voir si quelqu'un sait comment le faire, soit directement avec jQuery, soit par une autre option.


Answers

Vous pouvez simplement envelopper votre appel de liaison d'événement dans une fonction, puis l'appeler deux fois: une fois sur le document prêt et une fois après votre événement qui ajoute les nouveaux éléments DOM. Si vous faites cela, vous voudrez éviter de lier le même événement deux fois sur les éléments existants, vous aurez donc besoin soit de délier les événements existants ou (mieux) de ne lier que les éléments DOM nouvellement créés. Le code ressemblerait à ceci:

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

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

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

Il y a une bonne explication dans la documentation de on() .

En bref:

Les gestionnaires d'événements sont liés uniquement aux éléments actuellement sélectionnés. ils doivent exister sur la page au moment où votre code appelle .on() .

Ainsi, dans l'exemple suivant #dataTable tbody tr doit exister avant que le code ne soit généré.

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

Si un nouveau code HTML est injecté dans la page, il est préférable d'utiliser des événements délégués pour attacher un gestionnaire d'événements, comme indiqué ci-après.

Les événements délégués ont l'avantage de pouvoir traiter les événements à partir d'éléments descendants qui sont ajoutés au document ultérieurement. Par exemple, si la table existe, mais que les lignes sont ajoutées dynamiquement à l'aide de code, les éléments suivants le gèrent:

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

En plus de leur capacité à gérer les événements sur les éléments descendants qui ne sont pas encore créés, un autre avantage des événements délégués est leur potentiel de charge beaucoup plus faible lorsque de nombreux éléments doivent être surveillés. Dans une table de données contenant 1 000 lignes dans son tbody , le premier exemple de code attache un gestionnaire à 1 000 éléments.

Une approche d'événements délégués (le second exemple de code) attache un gestionnaire d'événements à un seul élément, le tbody , et l'événement n'a besoin que d'un niveau supérieur (du tr cliqué au tbody ).

Remarque: Les événements délégués ne fonctionnent pas pour SVG .


Essayez d'utiliser .live() au lieu de .bind() ; le .live() liera .hover à votre case à cocher après l'exécution de la requête Ajax.


C'est une solution JavaScript pure sans bibliothèques ni plugins:

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

hasClass est

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

Démonstration en direct

Le crédit va à Dave et Sime Vidas

En utilisant des JS plus modernes, hasClass peut être implémenté comme:

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

Tout objet existant au moment où l'événement est lié et si votre page créait de manière dynamique des éléments avec le bouton de nom de classe, vous lieriez l'événement à un parent qui existe déjà.

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


Essayez comme ça -

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

Une autre solution consiste à ajouter l'écouteur lors de la création de l'élément. Au lieu de placer l'écouteur dans le corps, vous placez l'écouteur dans l'élément au moment où vous le créez:

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

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


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

Je préfère utiliser le sélecteur et je l'applique sur le document.

Cela se lie sur le document et sera applicable aux éléments qui seront rendus après le chargement de la page.

Par exemple:

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

Prenez note de la classe "MAIN" l'élément est placé, par exemple,

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

Dans le scénario ci-dessus, l'objet MAIN que jQuery va regarder est "container".

Ensuite, vous aurez essentiellement des noms d'éléments sous le conteneur tels que ul , li , et select :

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

tu pourrais utiliser

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

ou

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

ces deux méthodes sont équivalentes mais ont un ordre différent de paramètres.

voir: Événement de délégué jQuery


La logique derrière cette chose est la présence de l'élément où vous devez lier votre événement. Si vous pensez que votre élément viendra dans un certain temps ou après un certain temps après avoir chargé votre site Web, il est préférable d'utiliser la délégation d'événements et cette simple ligne de code suffit juste.

 $(document).on( 'eventName', '.elementName', function () { ... do your work 
}); 

Ici eventName peut être n'importe quel événement comme click, mouseover, mouseleave, entrée, changement ...


Vous pouvez ajouter des événements aux objets lorsque vous les créez. Si vous ajoutez les mêmes événements à plusieurs objets à des moments différents, la création d'une fonction nommée peut être le chemin à parcourir.

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 */ )
;

Liaison d'événements sur des éléments créés dynamiquement

Élément unique:

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

Élément enfant

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

Notez le * ajouté. Un événement sera déclenché pour tous les enfants de cet élément.

J'ai remarqué que:

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

Ça ne marche plus, mais ça fonctionnait avant. J'utilise jQuery de Google CDN , mais je ne sais pas s'ils l'ont changé.


Voici pourquoi les éléments créés dynamiquement ne répondent pas aux 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>

Pour contourner ce problème, vous devez écouter tous les clics et vérifier l'élément source:

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>

Ceci est appelé "Délégation d'événements". Bonne nouvelle, c'est une fonctionnalité intégrée à 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>


Vous pouvez utiliser la méthode live () pour lier des éléments (même nouvellement créés) à des événements et des gestionnaires, comme l'événement onclick.

Voici un exemple de code que j'ai écrit, où vous pouvez voir comment la méthode live () lie les éléments choisis, même nouvellement créés, aux événements:

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

Utilisez la méthode .on() de jQuery on() pour attacher des gestionnaires d'événements à l'élément live.

De plus, à partir de la version 1.9, la méthode .live() est supprimée.


$("<div/>").attr('id','new').appendTo('body');    

Cela va créer une nouvelle div avec id "nouveau" dans le corps.





javascript jquery events unobtrusive-javascript