web-dev-qa-db-fra.com

Comment attacher des événements à des éléments HTML dynamiques avec jQuery?

Supposons que j’ai du code jQuery qui attache un gestionnaire d’événements à tous les éléments de classe .myclass.

Par exemple:

$(function(){
    $(".myclass").click( function() {
        // do something
    });
});

Et mon HTML pourrait être comme suit:

<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>

Cela fonctionne sans problème. Cependant, déterminez si les éléments .myclass ont été écrits dans la page à un moment ultérieur.

Par exemple:

<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
    $("#anchor1").click( function() {
        $("#anchor1").append('<a class="myclass" href="#">test4</a>');
    });
});
</script>

Dans ce cas, le lien test4 est créé lorsqu'un utilisateur clique sur a#anchor1.

Le lien test4 n'a pas le gestionnaire click() associé, même s'il a class="myclass".

En gros, j'aimerais écrire le gestionnaire click() une fois et l'appliquer à la fois au contenu présent au chargement de la page et au contenu importé plus tard via AJAX/DHTML. Une idée de comment je peux résoudre ce problème?

507
frankadelic

J'ajoute une nouvelle réponse pour refléter les modifications apportées aux versions ultérieures de jQuery. La méthode .live () est obsolète à partir de jQuery 1.7.

De http://api.jquery.com/live/

Depuis jQuery 1.7, la méthode .live () est obsolète. Utilisez .on () pour attacher des gestionnaires d’événements. Les utilisateurs d'anciennes versions de jQuery doivent utiliser .delegate () plutôt que .live ().

Pour jQuery 1.7+, vous pouvez attacher un gestionnaire d'événements à un élément parent à l'aide de .on (), puis passer le sélecteur a combiné à 'myclass' comme argument.

Voir http://api.jquery.com/on/

Donc au lieu de ...

$(".myclass").click( function() {
    // do something
});

Tu peux écrire...

$('body').on('click', 'a.myclass', function() {
    // do something
});

Cela fonctionnera pour toutes les balises avec "myclass" dans le corps, qu'elles soient déjà présentes ou ajoutées dynamiquement ultérieurement.

La balise body est utilisée ici car l'exemple n'a pas de balise entourant statique, mais toute balise parent qui existe lors de l'appel de la méthode .on fonctionnera. Par exemple, une balise ul pour une liste à laquelle seront ajoutés des éléments dynamiques ressemblerait à ceci:

$('ul').on('click', 'li', function() {
    alert( $(this).text() );
});

Tant que la balise ul existe, cela fonctionnera (aucun élément li n’existe encore).

861
Sean

Parfois, faire ceci (la réponse votée par le haut) n'est pas toujours suffisant:

$('body').on('click', 'a.myclass', function() {
    // do something
});

Cela peut poser problème en raison du déclenchement des gestionnaires d'événements de la commande. Si vous vous trouvez en train de le faire, mais que cela cause des problèmes en raison de l'ordre dans lequel il est traité. Vous pouvez toujours inclure cela dans une fonction, qui, lorsqu'elle est appelée, "rafraîchit" l'auditeur.

Par exemple:

function RefreshSomeEventListener() {
    // Remove handler from existing elements
    $("#wrapper .specific-selector").off(); 

    // Re-add event handler for all matching elements
    $("#wrapper .specific-selector").on("click", function() {
        // Handle event.
    }
}

Parce que c'est une fonction, chaque fois que je configure mon auditeur de cette façon, je l'appelle généralement sur le document prêt:

$(document).ready(function() {
    // Other ready commands / code

    // Call our function to setup initial listening
    RefreshSomeEventListener();
});

Ensuite, chaque fois que vous ajoutez un élément ajouté dynamiquement, appelez à nouveau cette méthode:

function SomeMethodThatAddsElement() {
    // Some code / AJAX / whatever.. Adding element dynamically

    // Refresh our listener, so the new element is taken into account
    RefreshSomeEventListener();
}

Espérons que cela aide!

Cordialement,

79
Chandler Zwolle

Après jQuery 1.7, les méthodes préférées sont . On () et . Off ()

La réponse de Sean montre un exemple.

Maintenant obsolète:

Utilisez les fonctions jQuery .live() et .die() . Disponible dans jQuery 1.3.x

De la docs:

Pour afficher le texte de chaque paragraphe dans une zone d’alerte chaque fois qu’on clique dessus:

$("p").live("click", function(){
  alert( $(this).text() );
});

En outre, le plugin livequery effectue cette opération et prend en charge plusieurs événements.

36
Matt Brunell

Si vous ajoutez une pile d'ancres au DOM, examinez plutôt la délégation d'événements.

Voici un exemple simple:

$('#somecontainer').click(function(e) {   
  var $target = $(e.target);   
  if ($target.hasClass("myclass")) {
    // do something
  }
});
5
ScottE

Lie un gestionnaire à un événement (tel que click) pour tous les éléments correspondants actuels et futurs. Peut également lier des événements personnalisés.

texte du lien

$(function(){
    $(".myclass").live("click", function() {
        // do something
    });
});
3
andres descalzo

Vous pouvez lier un événement de simple clic à une page pour tous les éléments, peu importe s'ils figurent déjà sur cette page ou s'ils arriveront ultérieurement, comme ceci:

$(document).bind('click', function (e) {
   var target = $(e.target);
   if (target.is('.myclass')) {
      e.preventDefault(); // if you want to cancel the event flow
      // do something
   } else if (target.is('.myotherclass')) {
      e.preventDefault();
      // do something else
   }
});

L'utilise depuis un moment. Fonctionne comme un charme.

Dans jQuery 1.7 et versions ultérieures, il est recommandé d'utiliser .on() à la place de bind ou de toute autre méthode de délégation d'événement, mais .bind() fonctionne toujours.

2
i--

Si vous utilisez jQuery 1.3+, utilisez . live ()

Lie un gestionnaire à un événement (tel que click) pour tous les éléments correspondants actuels et futurs. Peut également lier des événements personnalisés.

1
redsquare

Vous souhaitez utiliser la fonction live(). Voir la documentation .

Par exemple:

$("#anchor1").live("click", function() {
    $("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
1
Adam Bellaire