529 votes

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

Supposons que je dispose d'un code jQuery qui associe un gestionnaire d'événements à tous les éléments de la classe .myclass .

Par exemple :

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

Et mon code HTML pourrait être le suivant :

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

Cela fonctionne sans problème. Cependant, il faut se demander si le .myclass ont été inscrits sur 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 test4 est créé lorsqu'un utilisateur clique sur a#anchor1 .

En test4 n'a pas le lien click() qui lui est associé, même s'il a un class="myclass" .

En fait, je voudrais écrire le click() une seule fois et l'appliquer à la fois au contenu présent lors du chargement de la page et au contenu apporté ultérieurement par l'intermédiaire de AJAX / DHTML . Une idée sur la façon de résoudre ce problème ?

904voto

Sean Points 3056

J'ajoute une nouvelle réponse pour refléter les changements dans les versions ultérieures de jQuery. La méthode .live() est obsolète depuis jQuery 1.7.

En 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() de préférence à .live().

Pour jQuery 1.7+, vous pouvez attacher un gestionnaire d'événements à un élément parent en utilisant .on(), et en passant le sélecteur a combiné avec 'myclass' comme argument.

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

Ainsi, au lieu de...

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

Vous pouvez écrire...

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

Cela fonctionnera pour toutes les balises a avec 'myclass' dans le corps, qu'elles soient déjà présentes ou ajoutées dynamiquement par la suite.

La balise body est utilisée ici car l'exemple n'avait pas de balise statique environnante plus proche, mais toute balise parentale existant au moment de l'appel de la méthode .on fonctionnera. Par exemple, une balise ul pour une liste à laquelle des éléments dynamiques seront ajoutés ressemblerait à ceci :

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

Tant que la balise ul existe, cela fonctionnera (il n'est pas nécessaire d'avoir des éléments li).

86voto

Chandler Zwolle Points 41

Parfois, en faisant cela (la réponse la plus votée) n'est pas toujours suffisante :

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

Cela peut poser un problème en raison de l'ordre dans lequel les gestionnaires d'événements sont déclenchés. Si vous vous retrouvez à faire cela, mais que cela pose des problèmes à cause de l'ordre dans lequel c'est traité Vous pouvez toujours l'intégrer 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.
    }
}

Comme il s'agit d'une fonction, chaque fois que je configure mon écouteur de cette manière, je l'appelle généralement lorsque le document est 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 de manière dynamique, rappelez cette méthode :

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

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

J'espère que cela vous aidera !

Voir aussi,

36voto

Matt Brunell Points 7120

Après jQuery 1.7, les méthodes préférées sont les suivantes .on() y .off()

Réponse de Sean montre un exemple.

Désormais obsolète :

Utiliser les fonctions jQuery .live() y .die() . [ ] jQuery 1.3.x

D'après les documents :

Pour afficher chaque paragraphe dans une boîte d'alerte chaque fois que l'on clique dessus :

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

En outre, le livequery Le plugin permet d'effectuer cette opération et de prendre en charge d'autres événements.

6voto

ScottE Points 11633

Si vous ajoutez une pile d'ancres au DOM, envisagez 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
  }
});

3voto

andres descalzo Points 8392

Associe un gestionnaire à un événement (comme un clic) pour tous les éléments correspondants actuels et futurs. Il est également possible de lier des événements personnalisés.

texte du lien

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X