143 votes

jQuery comment lier l'événement onclick à un élément HTML ajouté dynamiquement

Je veux lier un événement onclick à un élément que j'insère dynamiquement avec jQuery.

Mais il n'exécute jamais la fonction liée. Je serais heureux si vous pouviez m'indiquer pourquoi cet exemple ne fonctionne pas et comment je peux le faire fonctionner correctement :

<!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" xml:lang="da" lang="da">
        <head>
          <title>test of click binding</title>

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
          <script type="text/javascript">

        jQuery(function(){
          close_link = $('<a class="" href="#">Click here to see an alert</a>');
          close_link.bind("click", function(){
            alert('hello from binded function call');
            //do stuff here...
          });

          $('.add_to_this').append(close_link);
        });
          </script>
        </head>
        <body>
          <h1 >Test of click binding</h1>
          <p>problem: to bind a click event to an element I append via JQuery.</p>

          <div class="add_to_this">
            <p>The link is created, then added here below:</p>
          </div>

          <div class="add_to_this">
            <p>Another is added here below:</p>
          </div>

        </body>
        </html>

EDIT : J'ai modifié l'exemple pour qu'il contienne deux éléments dans lesquels la méthode est insérée. Dans ce cas, le alert() n'est jamais exécuté. (merci à @Daff de l'avoir signalé dans un commentaire)

1 votes

Votre page d'exemple fonctionne correctement lorsque je l'ai testée avec FF 3.5.

0 votes

@Daff Malheureusement, vous avez raison ! J'ai donc apparemment extrait la partie de mon code qui fonctionne réellement. Merci de me l'avoir fait remarquer !

0 votes

@Daff, j'ai modifié l'exemple pour qu'il contienne deux endroits où insérer la méthode. Ensuite, il vraiment a cessé de fonctionner :)

324voto

aM1Ne Points 1251

Toutes ces méthodes sont obsolètes. Vous devez utiliser la méthode on pour résoudre votre problème.

Si vous voulez cibler un élément ajouté dynamiquement, vous devrez utiliser

$(document).on('click', selector-to-your-element , function() {
     //code here ....
});

qui remplace l'ancienne méthode .live() méthode.

15 votes

*selector-to-your-element* devrait être '.some-class' ou '#some-id'

0 votes

Mon problème était que je faisais quelque chose comme $('.row').on('click', function(){...}); au lieu de $(document).on('click','.row',function(){...});

7 votes

Se souvenir $(document) peut être n'importe quel élément qui ne change pas sur votre page. Cela permet d'éviter un bouillonnement excessif d'événements et d'accélérer votre JS. Par exemple. $(document) -> $('.example-container')

70voto

Tobias Points 1064

Le premier problème est que lorsque vous appelez append sur un ensemble jQuery contenant plus d'un élément, un clone de l'élément à ajouter est créé pour chacun d'entre eux et l'observateur d'événement attaché est donc perdu.

Une autre solution consisterait à créer un lien pour chaque élément :

function handler() { alert('hello'); }
$('.add_to_this').append(function() {
  return $('<a>Click here</a>').click(handler);
})

Un autre problème potentiel pourrait être que l'observateur d'événement est attaché avant que l'élément n'ait été ajouté au DOM. Je ne suis pas sûr que cela ait quelque chose à dire, mais je pense que le comportement peut être considéré comme indéterminé. Une approche plus solide serait probablement :

function handler() { alert('hello'); }
$('.add_to_this').each(function() {
  var link = $('<a>Click here</a>');
  $(this).append(link);
  link.click(handler);
});

2 votes

Il y a un problème lorsqu'il faut lier les clics sur des éléments annexés par d'autres fonctions. C'est pourquoi je suggère d'utiliser la réponse aM1Ne.

2 votes

En effet, lorsque vous ciblez des structures de balisage connues créées par un autre code. Mais ici, il a inséré les éléments lui-même, et il n'y a pas de sélecteur clair pour eux (il s'agit simplement d'une ancre, qui peut en avoir plusieurs), de sorte qu'il devrait ajouter des balises supplémentaires pour pouvoir cibler l'élément. Dans ce cas, il est tout aussi facile d'attacher le gestionnaire à l'élément directement, au lieu de capturer tous les clics et de tester la correspondance du sélecteur.

0 votes

Je comprends votre réponse, je ne voulais pas dire qu'elle était fausse. Il est certain qu'être capable d'injecter dynamiquement du html (comme un ul li d'images chargées avec ajax ou un scroll infini) et avoir déjà des boutons liés à une action (comme une lightbox), c'est beaucoup plus confortable.

51voto

Brother Erryn Points 803

Qu'en est-il de la méthode Live ?

$('.add_to_this a').live('click', function() {
    alert('hello from binded function call');
});

Néanmoins, ce que vous avez fait semble fonctionner. Il y a un autre message qui est assez similaire.

0 votes

Vous avez raison de dire que cela a fonctionné, c'est une erreur de ma part. J'ai donc modifié la question.

0 votes

Oui, ce genre de problème est exactement ce que les événements en direct sont censés résoudre.

0 votes

Le problème n'est pas lié aux événements en direct, même si, dans ce cas, un événement en direct le résoudrait. La réponse fournie par Daff résout également le problème, et ce sans ajouter le nouveau concept d'événements en direct à l'équation.

22voto

MrCode Points 34968

J'arrive un peu tard à la fête, mais je me suis dit que j'allais essayer de dissiper quelques idées fausses sur les gestionnaires d'événements de jQuery. Depuis jQuery 1.7, .on() doit être utilisé à la place de l'option obsolète .live() pour déléguer des gestionnaires d'événements à des éléments qui sont créés dynamiquement à tout moment après l'attribution du gestionnaire d'événements.

Cela dit, il ne s'agit pas d'une simple commutation live para on car la syntaxe est légèrement différente :

Nouvelle méthode (exemple 1) :

$(document).on('click', '#someting', function(){

});

Méthode obsolète (exemple 2) :

$('#something').live(function(){

});

Comme indiqué ci-dessus, il existe une différence. La torsion est .on() peut en fait être appelé de la même manière que .live() en passant le sélecteur à la fonction jQuery elle-même :

Exemple 3 :

$('#something').on('click', function(){

});

Cependant, sans utiliser $(document) comme dans l'exemple 1, l'exemple 3 ne fonctionnera pas pour les éléments créés dynamiquement. L'exemple 3 convient parfaitement si vous n'avez pas besoin de la délégation dynamique.

Faut-il utiliser $(document).on() pour tout ?

Cela fonctionnera, mais si vous n'avez pas besoin de la délégation dynamique, il serait plus approprié d'utiliser l'exemple 3, car l'exemple 1 exige un peu plus de travail de la part du navigateur. Il n'y aura pas d'impact réel sur les performances, mais il est logique d'utiliser la méthode la plus appropriée à votre usage.

Faut-il utiliser .on() au lieu de .click() si aucune délégation dynamique n'est nécessaire ?

Pas nécessairement. Ce qui suit n'est qu'un raccourci pour l'exemple 3 :

$('#something').click(function(){

});

Ce qui précède est parfaitement valable et c'est donc une question de préférence personnelle quant à la méthode à utiliser lorsqu'aucune délégation dynamique n'est nécessaire.

Références :

2voto

Daff Points 22358

Considérez ceci :

jQuery(function(){
  var close_link = $('<a class="" href="#">Click here to see an alert</a>');
      $('.add_to_this').append(close_link);
      $('.add_to_this').children().each(function()
      {
        $(this).click(function() {
            alert('hello from binded function call');
            //do stuff here...
        });
      });
});

Il fonctionnera parce que vous l'associez à chaque élément spécifique. C'est pourquoi, après avoir ajouté votre lien au DOM, vous devez trouver un moyen de sélectionner explicitement l'élément ajouté en tant qu'élément JQuery dans le DOM et de lier l'événement de clic à cet élément.

Le meilleur moyen sera probablement - comme suggéré - de le lier à une classe spécifique via la méthode live.

0 votes

Merci pour la réponse, Daff. Il ne peut pas être vrai que je ne peux ajouter des écouteurs d'événements qu'aux éléments du DOM. Cependant, je vais pour l'instant modifier mon code pour le faire. (Cela ne devrait pas poser de problème car j'ajoute simplement une classe css spéciale pour les liens ajoutés).

0 votes

Oui, vous avez raison, ce n'est pas le DOM (il fonctionne en fait avec un seul DOM), désolé. Mais j'ai aussi découvert que lier des éléments créés dynamiquement semble être assez ennuyeux, tant qu'ils ne sont pas sélectionnables par un sélecteur jQuery distinct.

0 votes

"hello from BOUND function call" (bonjour de l'appel de la fonction BOUND). Désolé, il y en a trop sur ce post (une page entière ; questions et réponses) et je veux juste aider, vous savez, à clarifier les choses.

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