Files
stagiaire/SOLUTIONS_contact_4.md
T

6.3 KiB
Raw Blame History

Solutions — Niveau 5 contact (PROCHAINE_ETAPE_contact_4.md)

🛑 À NE REGARDER QU'EN DERNIER RECOURS. Cherche d'abord par toi-même (au moins 1015 min, doc MDN à l'appui). Quand tu lis une réponse : lis-la, ferme le fichier, et réécris-la de mémoire. C'est comme ça que ça rentre.

Le code ci-dessous est un exemple correct. Le tien peut être différent et tout aussi valable.


🧪 Exo 1 — map

const noms = equipe.map(function (membre) {
    return membre.nom;
});
console.log(noms);   // ["Mélissa", "Guillaume"]

💬 « map ou filter ? » filter garde/jette des éléments (la liste rétrécit). map transforme chaque élément (la liste garde la même taille). Ici on veut transformer chaque objet en son nom → map.


🧪 Exo 2 — find

const personne = equipe.find(function (membre) {
    return membre.partie === "Page contact";
});

if (personne) {
    console.log(personne.nom);
} else {
    console.log("Personne ne correspond.");
}

💬 « Pourquoi le if (personne) ? » Si aucun élément ne correspond, find renvoie undefined. Faire personne.nom planterait. On vérifie d'abord. (Variante moderne : personne?.nom — cherche optional chaining.)


🧪 Exo 3 — reduce

Avec une boucle (plus lisible pour commencer) :

let totalKm = 0;
for (const v of vehicules) {
    totalKm = totalKm + v.km;
}

La même chose en reduce :

const totalKm = vehicules.reduce(function (somme, v) {
    return somme + v.km;
}, 0);   // ← 0 = la valeur de départ
console.log(totalKm);

💬 « À quoi sert le 0 à la fin ? » C'est la valeur de départ de l'accumulateur (somme). Pour une somme on part de 0 ; pour multiplier on partirait de 1.


🧪 Exo 4 — Délégation d'événements

Quand tu génères les lignes, marque chaque ligne avec le nom (un attribut data-…) :

function creerLigne(membre) {
    const tr = document.createElement("tr");
    tr.dataset.nom = membre.nom;   // devient data-nom="..." dans le HTML
    // ... (les <td> comme avant)
    return tr;
}

Puis un seul écouteur, sur le parent qui ne bouge pas :

const corps = document.getElementById("corps_equipe");
corps.addEventListener("click", function (event) {
    const ligne = event.target.closest("tr");   // la <tr> cliquée, peu importe la <td>
    if (ligne) {
        alert("Membre : " + ligne.dataset.nom);
    }
});

💬 « Pourquoi ne pas mettre l'écouteur sur chaque <tr> ? » Parce que tes lignes sont recréées à chaque recherche/tri : il faudrait tout réattacher à chaque fois. En écoutant le parent (qui, lui, ne change pas), ça marche même pour les lignes créées plus tard. 💬 « À quoi sert closest("tr") ? » Le clic peut tomber sur une <td> ; closest remonte jusqu'à la <tr> qui la contient.


🧪 Exo 5 — Debounce sur la recherche

let minuteur;   // garde la trace du minuteur en cours

champRecherche.addEventListener("input", function () {
    clearTimeout(minuteur);                 // on annule le précédent
    minuteur = setTimeout(function () {     // on en relance un
        const mot = champRecherche.value.toLowerCase();
        const resultats = equipe.filter(m => m.nom.toLowerCase().includes(mot));
        afficherEquipe(resultats);
    }, 300);                                 // 300 ms après la DERNIÈRE frappe
});

💬 « Comment ça « attend » ? » À chaque frappe, on annule le minuteur précédent (clearTimeout) et on en repart un de 300 ms. Tant que tu tapes, il est sans cesse annulé ; il ne se déclenche que quand tu fais une pause.


🧪 Exo 6 — Modules export / import

navbar.js :

export function creerNavbar(pageActive) {
    return `... ton HTML de navbar ...`;
}

contact.js (tout en haut) :

import { creerNavbar } from "./navbar.js";
document.body.insertAdjacentHTML("afterbegin", creerNavbar("contact"));

HTML :

<script type="module" src="../contact.js"></script>

💬 « Depuis que j'utilise type="module", mes autres scripts ne se voient plus ! » Normal : chaque module a son propre espace. Une variable d'un fichier n'est plus visible ailleurs sauf si tu l'exportes et l'importes. C'est justement le but : plus de variables globales qui se marchent dessus. 💬 « Erreur CORS au chargement du module. » Comme fetch, les modules exigent un serveur : python3 -m http.server puis http://localhost:8000/... (pas file://).


🧪 Exo 7 — Vraie API en ligne

async function chargerUtilisateurs() {
    const liste = document.getElementById("liste_users");
    try {
        const reponse = await fetch("https://jsonplaceholder.typicode.com/users");
        const users = await reponse.json();
        for (const u of users) {
            const li = document.createElement("li");
            li.textContent = `${u.name}${u.email}`;
            liste.append(li);
        }
    } catch (erreur) {
        console.error(erreur);
    }
}
chargerUtilisateurs();

💬 « Comment je sais que les clés s'appellent name et email ? » J'ai d'abord ouvert https://jsonplaceholder.typicode.com/users dans le navigateur pour voir la forme des données. Fais toujours ça avant d'afficher. 💬 « Ça marche sur le web mais mon fichier local non ? » Une API en ligne autorise les requêtes externes (CORS) ; un fichier local ouvert en file:// non. D'où le serveur local pour tes propres fichiers.


🧪 Exo 8 — FormData

formulaire.addEventListener("submit", function (evenement) {
    evenement.preventDefault();
    const data = new FormData(formulaire);
    const valeurs = Object.fromEntries(data);
    console.log(valeurs);   // { prenom: "...", email: "...", contacter: "..." }
});

💬 « FormData me renvoie du vide ! » Vérifie que chaque champ a un attribut name (pas seulement id). FormData lit les champs par leur name. 💬 « C'est mieux que getElementById partout ? » Pour lire tout un formulaire d'un coup, oui : une ligne au lieu d'un getElementById par champ. Pour un seul champ ponctuel, getElementById reste très bien.


🆘 Encore bloquée après la solution ?

Note : ce que tu attendais, ce qui se passe à la place, et ce qu'affiche la Console (F12). Avec ces 3 infos, on débloque vite.