ERREUR: Confondre les propriétés DOM et les attributs HTML ([src] vs src)

Définitions

Attribut HTML

Un attribut HTML permet de modifier l’affichage ou le comportement d’une balise HTML. Il s’utilise dans le code source HTML.

Par exemple, la balise <img> possède un attribut src qui contient le chemin de l’image à afficher.

<img src="images/flower.jpg">

Propriété DOM

Un navigateur se représente une page web comme une arborescence qu’on appelle le DOM, ou Document Object Model. Chaque balise HTML de la page correspond à un “noeud” dans le DOM. Chaque noeud possède des propriétés et des méthodes qui permettent de le manipuler en JavaScript.

Ainsi dans le DOM, la balise <img> présentée plus haut est une instance de HTMLImageElement, et possède des propriétés comme src ou complete.

Pour récupérer la première image affichée dans la page et changer son fichier, on pourrait écrire en JavaScript :

const imageRef = document.getElementsByTagName('img')[0];
imageRef.src = 'images/car.jpg';

Comparaison attribut HTML et propriété DOM

HTMLDOM (JavaScript)
Balise <img>Instance de HTMLImageElement
Attribut srcPropriété src
Utilisation :
<img src="images/flower.jpg">
Utilisation :
const imageRef = document.getElementsByTagName('img')[0];
console.log(imageRef.src);

Pourquoi confond-t-on attribut HTML et propriété DOM ?

Il y a deux raisons qui expliquent la confusion fréquente entre attribut HTML et propriété DOM :

  • L’attribut HTML et la propriété DOM portent souvent le même nom. Exemple : on utilise “src” pour l’attribut <img src=""> ET pour la propriété DOM HTMLImageElement.src.
  • Dans Angular, on utilise les propriétés DOM directement dans le HTML, en écrivant par exemple <img [src]="variable">. En code “classique”, les deux sont bien séparés : on utilise les attributs HTML en HTML et les propriétés DOM en JavaScript.

Mais attributs et propriétés sont deux choses différentes. Il existe des propriétés DOM qui n’ont pas d’attribut HTML équivalent. Par exemple, la propriété HTMLImageElement.complete retourne true si le navigateur a fini de charger l’image. Il n’y a pas d’attribut HTML <img complete>.

Dans le binding de propriété Angular, ce sont bien les propriétés DOM qu’il faut utiliser.

Ainsi, les syntaxes suivantes sont CORRECTES (j’ai mis en commentaire le nom de la propriété DOM ciblée) :

<img [src]="foo">             <!-- HTMLImageElement.src -->
<a [href]="foo">...</a>       <!-- HTMLAnchorElement.href -->
<p [innerHTML]="foo">...</p>  <!-- HTMLParagraphElement.innerHTML -->

Et les syntaxes suivantes sont INCORRECTES :

<p innerHTML="...">    <!-- L'attribut innerHTML n'existe pas sur la balise p -->
<img src="{{ foo }}">  <!-- Fonctionne, mais pas recommandé -->

La syntaxe <img src="{{ foo }}"> n’est pas recommandée, car au lieu de cibler la propriété DOM, on écrit dans l’attribut HTML avec une interpolation. C’est un problème parce que si le HTML est affiché avant que la propriété soit interpolée, ça fera une erreur 404.

Voir comment trouver la liste des propriétés DOM d’une balise donnée.


 

Cette recette vous a plus ? Rejoignez-nous à Paris pour une formation Angular de 3 jours dans laquelle vous coderez une application professionnelle que vous déploierez en production.

Le jour où j'ai enfin compris Angular