Bonsoir !

Je suis actuellement en train d'apprendre le JS et plus particulièrement le Jquery et je m'essayai à créer une ToDoList sur Code Pen (https://codepen.io/Jonathan_Design/pen/OJwqXrO) et je me suis heurté un à probleme quand je souhaitais supprimer ma ligne de ToDo après un clique sur le petit icone de la poubelle.

A la base j'ai écris ce code :

" $(".todolist__list__raw__trash").click(function(){ $(this).parent().remove(); }); "

et après essaie, le code ne réagissait pas comme convenue , c'est à dire supprimer le parent apres avoir cliqué sur l'icone.

j'ai donc cherché sur le net et sur un forum j'ai fini par trouvé ceci (qui fonctionne parfaitement) :

" $(document).on('click', '.todolist__list__raw__trash', function() { $(this).parent().remove(); }); "

Ce que je souhaiterai c'est comprendre dans un premier temps pourquoi ma première syntaxe ne fonctionne pas correctement, étant en apprentissage (est tétu !), je tiens à savoir pourquoi :)

Et dans un deuxieme temps, pourquoi je dois faire appel au document, les 2 syntaxes se ressemble mais je comprends pas pourquoi ça ne s'écrit pas de la même façon.

Merci à vous
Jonathan

6 réponses


  • La première syntaxe dit "écoute le clic sur les éléments .todolist__list__raw__trash
  • La seconde syntaxe dit "écoute le clic sur le document, puis regarde la cible de l'évènement (e.target) et voit si ça correspond à .todolist__list__raw__trash.

La seconde syntaxe permet par exemple d'avoir un écouteur qui fonctionne sur un élément qui n'existe pas encore dans le DOM au moment où il est créé. L'inconvénient et la performance car cette vérification va se déclencher à chaque clic sur le document.

À noter également que la deuxième syntaxe utilise la délégation d'évènement, qui est moins gourmande en ressource. Le gestionnaire d''évènement n'est appliqué qu'à un seul élément contrairement à la 1ère syntaxe qui va l'appliquer à chaque élément concerné.

Il vaut mieux être plus restrictif sur le sélecteur en prenant la liste dans laquelle les todo seront ajoutés :
$('.todolist__list').on('click', '.todolist__list__raw__trash', function() { $(this).parent().remove(); });

Et dans ton exemple tu fais

$(".todolist__list__plus").click(function(){
      $(".todolist__list").append([

c'est à dire qu'à chaque clic ton nav va devoir chercher $('.todolist__list'). Vu que l'élément .todolist__list ne change pas tu peux le mettre "en cache" :

const $todoList = $(".todolist__list")
$(".todolist__list__plus").click(function(){
      $todoList.append([

Merci beaucoup pour vos réponses, je vous l'avoue, étant débutant en JS il me faut beaucoup de temps pour comprendre vos messages :)
Si je peux me permettre, j'y pense depuis hier mais je comprends toujours pas pourquoi la synstaxe (ci dessous) ne fonctionne pas, je m'explique :

$(".todolist__list__raw__trash").click(function(){
$(this).parent().remove();
});

en créant cette syntaxe, j'ai l'impression de dire, quand je clique sur l'icone "poubelle" je veux "remove" le parent et tout ce qu'il y a dedans , mais apparemment ce n'est pas le cas :)

Ça dépend de quand tu ajoutes cet écouteur d'évènement.
Si tu le mets quand tu n'as pas de todo dans ta page alors les nouveaux todo n'auront pas magiquement l'écouteur.

Tu as le choix :

  1. tu vires et recrées les écouteurs quand tu ajoutes une todo ce qui n'est pas optimisé :
    $(".todolist__list__raw__trash").off('click').click(function(){$(this).parent().remove();});
  2. tu écoutes les clics sur l'élément parent :
    $(".todolist__list").on('click', '.todolist__list__raw__trash', function() {
    console.log("ca marche")
    })

T'as aussi une erreur dans ton codepen actuel :
const todoTrash = document.querySelector(".todolsist__list__raw__trash:last-child");

Il faut changer todolsist__list__raw__trash en todolist__list__raw__trash

Et t'as bien mis const todoList = document.querySelector(".todolist__list"); mais à l'intérieur de la fonction. Si tu mets ça à l'extérieur alors ton nav n'aura pas besoin d'aller chercher .todolist__list à chaque fois que addRaw est appelé.
Oui, dans ce ce cas ce n'est plus une fonction pure mais tu peux soit voir ça plus tard, soit passer todolist en param à ta fonction :

const todoList = document.querySelector(".todolist__list");

function addRaw(event, todolist) {
  // des trucs super qui utilisent todolist
}

Amuse toi bien !

vraiment merci beaucoup pour tes retours ! je viens de faire le test de passer todoList en dehors de la function et de l'ajouter en parametre de la fonction addRaw mais j'ai une erreur sur :

todoList.appendChild(newTodoDivRaw);
    //Uncaught TypeError: Cannot read properties of undefined (reading 'appendChild')

Je ne savais meme pas que je pouvais ajouter en paramêtre de fonction une variable et j'essaie veinement de comprendre les querySelector, par exemple des que j'ajoute de façon dynamique un element via JS, je peine à selectionner un élément de mon choix, c'est actuellement le cas avec l'icone des poubelles, je peux uniquement selectionner celle de ma première ligne car il est de base dans le HMTL, mais pas les autres.

Salut Jonathan.

Je voulais revenir vers ce sujet avant mais j'étais pas mal occupé.

Voilà un CodePen nettoyé : https://codepen.io/JoolsMcFly/pen/GRXRyyV
La partie HTML ne doit contenir que la balise body, les dépendances CSS et JS sont à ajouter depuis l'icône paramètres dans chacun des volets.

Pour ce qui est du comment gérer dynamiquement la suppression des todos : on écoute les clics sur l'élément parent (variable todolist) et on regarde si le clic a été fait sur l'élément fils qui nous intéresse. Si c'est le cas alors on remonte jusqu'au parent todolistlistraw et on vire le noeud.