JQuery ne voit pas l’élément que je viens de créer ?

Si vous avez l’habitude de faire du JQuery, voici un problème que vous avez probablement déjà du rencontrer : lors de l’ajout dynamique d’un nouvel élément, JQuery ne le voit pas, ce qui est logique car l’Event (par exemple un click) étant associé au chargement de la page, alors que l’élément en question n’existait pas encore.

Voici un exemple pour être plus clair :

$('body').append('<div class="clickme">Click !</div>');
$('.clickme').click(function () { /* ... */ });

Dans ce cas, l’évènement ne fonctionnera pas, l’élément .clickme n’étant pas connu au chargement de la page. La solution pour y remédier est d’utiliser .live() qui permet d’ajouter un handler (gestionnaire d’événement) pour tous les éléments, même ceux créés dynamiquement. Il permet donc -en gros- de rafraîchir le DOM.

Voici donc la bonne syntaxe a suivre :

$('.clickme').live('click', function() { /* ... */ });
11 commentaires
  1. Matthieu R. dit :

    Un petit complément d’information, même si live() parait magique (et elle l’est presque 😉 elle a ses petits inconvénients, dûs à son implémentation technique particulière :

    • elle ne s’applique pas à tous les événements (cf liste ci-dessous) et ne peux pas s’appliquer non-plus à une fonction « maison », voici la liste des event supportés :
    – jQ 1.3.x : click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, and mouseup.
    – jQ 1.4 supporte visiblement les événements plus « custom » de jQuery au delà des event JS traditionnels (je n’ai pas testé personnellement), supporte aussi que focus/focusin et blur/focusout
    – jQ 1.4.1 supporte hover, mouseenter, mouseleave

    • elle doit être appelée immédiatement après le sélecteur (pas de find, siblings et autres fonctions en cascade derrière le sélecteur).

    • personnellement j’ai constaté que certains sélecteurs très poussés peuvent également ne pas fonctionner, comme des sélecteurs de hiérarchie combinés à des clauses :not()… à tester.

    Quand live() n’est pas possible, le mieux est alors de se rabattre sur un bon vieux callback 😉

  2. Romain W. dit :

    Merci Beaucoup, un bon référencement sur Google de ton article qui m’as permis de trouver la solution à mon petit souci.

  3. Julien G dit :

    Merci beaucoup! Après une journée à retourner ma fonction dans tout les sens ton article m’a été d’une grande aide 🙂

  4. Nooi dit :

    merci pour ton article. Comme le dit romain grâce à ton bon référencement pas besoin de passer des heures à chercher sur google =)

  5. Roxarmy dit :

    Merci de ton aide, j’ai passé des heures à comprendre avant de tomber sur ton article.
    Simple et bien expliqué !

  6. Julien Breux dit :

    Juste pour information, si l’élément est créé selon les bonnes pratiques. Comme ceci :

    var element = jQuery(‘‘, {
    id : ‘someId’,
    className : ‘someClass’,
    href : ‘somePath.html’,
    click: function() { /***/ }
    });
    jQuery(‘body’).append(element);

    Alors aucun problème 😉

  7. Ben dit :

    bien vu Julien, merci 🙂

  8. Yannux dit :

    Je confirme les commentaires précédents, j’allais me tirer les cheveux !
    A noter que .live est déprécié dans les version 1.7 et +, il faut utiliser .on => http://api.jquery.com/live/

  9. Math dit :

    Peut-il fonctionner sur un include PHP?

  10. Migli dit :

    Même problème pour accéder au DOM après un appel ajax.

    Ta solution permet d’associer des événements aux éléments créés, mais pas d’y accéder directement (par ex : $(‘.clickme’).css())

    En fait, ajax renvoie le contenu html ‘as plain text’ pour citer la doc.

    Pour accéder au dom depuis le fichier appelé, voici comment faire :

    Appel ajax :
    $.ajax({
    url: ‘fichier.php’,
    data: ‘var=valeur’,
    success: function(data, textStatus, jqXHR) {
    maFonction();
    }
    });

    Dans fichier.php :
    test

    var maFonction = function()
    {
    $(« #test »).css(‘color’, ‘#FC6C3F’); // jquery reconnait bien p#test
    };

  11. fabien veyret dit :

    De même que l’on peut précharger une fonction de click sur un élément encore pas existant pour le DOM :

    $(‘body’).on(‘click’, ‘.clickme’, function(){ /* … */ });

Laisser une réponse