Une liste qui s'allonge, une notification qui apparaît, une ligne de tableau ajoutée après un enregistrement : ces éléments n'existent pas dans le fichier HTML de départ. Ils sont fabriqués pendant que la page vit.
Une méthode suffit pour les créer, mais elle ne fait que la moitié du chemin : l'élément produit reste invisible tant qu'on ne l'a pas rattaché à la page.
Définition
document.createElement() fabrique un élément HTML à partir de son nom de balise et le rend, vide, sans parent et absent de la page. C'est un objet en mémoire, prêt à être rempli puis inséré.
const bouton = document.createElement("button");
bouton.textContent = "Valider";
bouton.className = "primaire";
bouton.type = "button";
console.log(bouton.parentNode); // null, il n'est nulle part
document.body.append(bouton); // maintenant il est dans la pageLe nom de balise n'est pas sensible à la casse pour un document HTML : createElement("DIV") et createElement("div") produisent le même élément.
Créer, remplir, insérer
La construction d'un élément se déroule toujours en trois temps, et oublier le troisième est l'erreur la plus fréquente.
- Créer avec
createElement, qui rend un élément détaché du document. - Remplir ses propriétés : textContent pour le texte, classList pour les classes, dataset pour les données sur mesure,
setAttributepour le reste. - Insérer avec
append,prepend,beforeouafter, selon la position voulue.
append accepte plusieurs arguments et des chaînes de caractères, là où l'ancien appendChild n'accepte qu'un seul nœud et le renvoie.
Insérer plusieurs éléments d'un coup
Ajouter cent éléments un par un déclenche cent modifications du document. Un fragment sert de sac intermédiaire : il se remplit hors de la page, puis se vide dedans en une seule opération.
const donnees = ["Paris", "Lyon", "Nantes"];
const fragment = document.createDocumentFragment();
for (const ville of donnees) {
const item = document.createElement("li");
item.textContent = ville;
fragment.append(item);
}
document.querySelector("ul").append(fragment);
// le fragment est vidé de ses enfants, seuls les li restentLa boucle for associée à of suffit ici, mais le principe reste le même avec Array.forEach() ou Array.map().
Un élément créé puis jamais inséré n'est pas une fuite : il disparaît dès que plus aucune variable ne le référence. En revanche, un élément retiré de la page mais conservé dans un tableau reste en mémoire, avec ses écouteurs.
Questions fréquentes
createElement ou innerHTML pour construire une liste ?
Les deux fonctionnent, mais ils ne présentent pas le même risque. innerHTML interprète la chaîne comme du balisage, donc toute donnée venue de l'extérieur doit être échappée avant. La construction élément par élément ne peut pas produire de balise involontaire, et elle permet de poser des écouteurs sur chaque nœud au moment où il est créé.
Pourquoi mon élément n'apparaît-il pas ?
Dans la quasi-totalité des cas, l'insertion manque : l'élément a été créé et rempli, mais jamais rattaché à un parent présent dans la page. La deuxième cause est un parent introuvable, quand le script s'exécute avant que le HTML ne soit analysé. Vérifiez la valeur rendue par querySelector() avant de chercher plus loin.
Comment créer une icône SVG ?
Pas avec cette méthode : un SVG appartient à un autre espace de noms, et un élément créé par createElement ne s'affichera pas. Il faut utiliser document.createElementNS en lui passant l'adresse de l'espace SVG en premier argument. C'est la seule différence, le reste de la construction est identique.