IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contributions JavaScript / AJAX Discussion :

Comment attribuer à des objets un onclick faisant appel à une variable de boucle ?


Sujet :

Contributions JavaScript / AJAX

  1. #1
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut Comment attribuer à des objets un onclick faisant appel à une variable de boucle ?
    Comment attribuer à des objets un onclick faisant appel à une variable de boucle ?

    Pour garder la structure actuelle de la question, je pense exposer le problème rencontré quand on utilise var — ce qui n’est pas inenvisageable aujourd’hui, compte tenu de la prolifération de docs JS obsolètes sur le Web — puis proposer une solution où l’on remplace simplement var par let, en expliquant très rapidement le fonctionnement de let.

    Je propose de rajouter un 3e paragraphe à l’attention de celles et ceux qui développent sur des vieilles plateformes où ES2015+ n’est pas disponible. Les débutantes et débutants ne savent pas forcément que même un framework ne peut pas « tasser » cette incompatibilité.

    Dans tous les cas, la solution actuelle me paraît obsolète, car elle utilise les propriétés expando, technique généralement déconseillée aujourd’hui. Je propose une solution utilisant une fonction anonyme (IIFE).

    Un peu hors sujet, je me suis interrogé sur le genre de div (« un div » ou « une div » ?). Je penche plutôt pour le féminin mais, comme c’est de l’ordre du détail, j’ai respecté la version originale.

    Dans des cas comme celui ci-dessous, où l’on souhaite créer des éléments et leur attribuer un événement onclick dépendant d’une variable de boucle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function foo() {
      for (var i = 0; i < 10; i++) {
        var MonDiv = document.createElement("div");
        MonDiv.textContent = "div " + i;
        MonDiv.onclick = function () { alert(i); };
        document.body.appendChild(MonDiv);
      }
    }
    Cette fonction est censée permettre de créer 10 nouveaux divs contenant les textes « div 1 », « div 2 », etc. et de les insérer dans la page. On leur attribue également un onclick avec pour but de faire un alert() de « 1 » sur le premier div, « 2 » sur le second, etc.

    Malheureusement cela ne fonctionne pas : les divs sont correctement créés et insérés mais au clic, tous affichent le message « 10 ». En fait, la valeur de i n’est pas évaluée au moment de la mise en place du onclick, mais seulement au moment où celui-ci est appelé. Or à ce moment, sa valeur vaut bien 10, la dernière valeur de la boucle.

    La solution moderne (fin 2017) est d’utiliser le mot-clé let, apparu avec ECMAScript 2015, qui fonctionne un peu comme var mais qui limite la portée des variables au bloc courant, en l’occurence le corps de la boucle for.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function foo() {
      for (let i = 0; i < 10; i++) {
        let MonDiv = document.createElement("div");
        MonDiv.textContent = "div " + i;
        MonDiv.onclick = function () { alert(i); };
        document.body.appendChild(MonDiv);
      }
    }
    Si vous développez dans un environnement où let n’est pas disponible, il faut recourir à une fonction anonyme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function foo() {
      for (var i = 0; i < 10; i++) {
        var MonDiv = document.createElement("div");
        MonDiv.textContent = "div " + i;
     
        (function (arg) {
          MonDiv.onclick = function () { alert(arg); };
        }(i));
     
        document.body.appendChild(MonDiv);
      }
    }
    Cela fonctionne car la fonction anonyme copie la valeur de i dans son argument arg au moment où elle est appelée, c’est-à-dire au moment où la boucle for est exécutée.
    Voilà, j’ai essayé de faire aussi clair et concis que possible, mais si vous trouvez qu’un passage mérite d’être reformulé, n’hésitez pas
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  2. #2
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Bonjour Watilin,
    effectivement il y a de la mise à jour dans l'air.

    J'utilise également une solution sans fonction anonyme, pour plus de lisibilité du code, via une fonction externe (ou pas d'ailleurs), ce qui en reprenant ton exemple donnerait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     var setHandleClick = function (elem, param) {
      elem.onclick = function () {
        alert(param);
      };
    };
    function foo() {
      var oElem;
      for (var i = 0; i < 10; i++) {
        // création élément
        oElem = document.createElement('div');
        oElem.textContent = 'div ' + i;
        // affectation fonction
        setHandleClick(oElem, i);
        // ajout élément au DOM
        document.body.appendChild(oElem);
      }
    }

Discussions similaires

  1. Comment débuguer des objets COM ?
    Par WebPac dans le forum Delphi
    Réponses: 5
    Dernier message: 14/10/2006, 19h28
  2. [WinForms]Comment partager des objets entre threads ?
    Par AiSpirit dans le forum Général Dotnet
    Réponses: 3
    Dernier message: 16/08/2006, 08h57
  3. [Access] Expression avec une clause SQL faisant appel à une variable
    Par elgringo2007 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 27/06/2006, 13h02
  4. Comment supprimer des objets
    Par akrobat dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 17/06/2006, 11h48
  5. Réponses: 13
    Dernier message: 09/05/2006, 16h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo