image auteur
Lucas BENTO-VERSACE 4min • 25-02-2022

Angular - Ng-container

Angular - Ng-container

Bienvenue sur CodeWise ! Si vous êtes nouveau ici, vous voudrez sans doute découvrir notre Starter Kit Angular : il contient une roadmap du parcours d'un dev Angular, ainsi qu'un cookbook des commandes les plus utiles et un extrait de formation. Cliquez ici pour le télécharger (c’est gratuit !)

Dans cet article vous allez découvrir à quoi sert le ng-container.

Définition ng-container

La balise <ng-container> est une balise qui peut contenir des directives structurelles mais qui n'est pas rendue (rendering) dans le DOM.

C'est à dire que si vous utilisez cette balise dans un template HTML de composant, elle n'apparaitra pas dans le DOM sur le navigateur de votre utilisateur. Mais quel est l'intérêt d'une balise qui n'apparait pas ?

En HTML pur, cela n'aurait aucun intérêt. Mais si vous utilisez Angular, cela vous permettra d'utiliser des fonctionnalités d'Angular, sans influencer le DOM de votre projet.

Voici 2 cas où la balise <ng-container> pourra vous être utile.

Dans quel cas l'utiliser ?

Combiner plusieurs directives structurelles

Vous ne pouvez pas utiliser plusieurs directives structurelles sur le même élément.

Par exemple, ce code vous renverrait une erreur :

1
2
3
4
5
<ul>
    <li *ngFor="let item of items" *ngIf="item.isValid">
        {{ item.name }}
    </li>
</ul>
exemple.component.html

Dans ce code, on essaye d'afficher tous les items valides dans une liste. Pour cela, vous devez utiliser une boucle *ngFor, combinée avec un *ngIf pour ne filtrer que les items valides.

Or, ceci est impossible avec Angular. Etant donné le fonctionnement des directives structurelles, les 2 directives ne peuvent pas se partager un même élément du DOM.

Pour corriger le problème, vous pourriez utiliser une balise qui ne génère pas d'affichage pour encadrer le <li> et ainsi poser les directives structurelles sur 2 balises différentes :

1
2
3
4
5
6
7
<ul>
    <div *ngFor="let item of items">
        <li  *ngIf="item.isValid">
            {{ item.name }}
        </li>
    </div>
</ul>
exemple.component.html

Ce code ne vous génèrera pas d'erreur et il rendra le résultat voulu à l'écran.

Mais cette solution n'est pas tout à fait satisfaisante. Vous voyez pourquoi ?

Premièrement, autour de chaque <li> vous allez devoir effectuer le rendering d'une <div> qui ne sert à rien au fonctionnement de votre page. Vous perdez en performances, et le problème s'aggrave si le nombre d'items augmente.

Et deuxièmement, la sémantique HTML est brisée ! Il est interdit de placer une balise <div> en enfant direct d'une balise <ul>. Essayer de passer votre page dans un validateur HTML W3C, vous verrez qu'il juge votre DOM invalide.

Alors comment faire ? Eh bien c'est là que le <ng-container> entre en jeu.

1
2
3
4
5
6
7
<ul>
    <ng-container *ngFor="let item of items">
        <li *ngIf="item.isValid">
            {{ item.name }}
        </li>
    </ng-container>
</ul>
ng-container.component.html

La balise <ng-container> ne rendra pas d'élément dans le DOM ce qui convient parfaitement à notre cas. On évite ainsi tout problème de performance du rendering, ainsi que le problème de sémantique HTML.

Utiliser avec ngTemplateOutlet

Quand vous utilisez un <ng-template> pour générer votre DOM avec Angular, vous devez vous y prendre en 2 étapes :

  • Déclarer un <ng-template>
  • Le faire charger à différents endroits de votre page avec la directive ngTemplateOutlet

La directive ngTemplateOutlet peut s'appliquer à n'importe quel élément, mais Angular vous recommande de l'utiliser avec <ng-container>.

Ainsi, le contenu du <ng-template> se retrouve projeté à l'emplacement de la directive sans être nécessairement encadré d'une <div> ou autre élément HTML.

Par exemple, imaginez une partie du DOM qui doit être répétée à plusieurs endroits de votre template HTML. Vous décidez de définir un <ng-template> pour éviter la répétition de code.

Voici ce que vous pourriez envisager :

1
2
3
4
5
6
7
8
9
<ng-container *ngTemplateOutlet="tmpl; context: {text: 'Hello'}">
</ng-container>

<ng-container *ngTemplateOutlet="tmpl; context: {text: 'World'}">
</ng-container>

<ng-template #tmpl let-text>
  <h1> {{ text }}</h1>
</ng-template>
ng-template-outlet.component.html

Le <h1> n'a été rédigé qu'une fois, mais il sera chargé 2 fois.

Le DOM résultant de ce code est le suivant :

1
2
3
<h1>Hello</h1>

<h1>World</h1>

Grâce au <ng-container>, vous n'avez que le contenu du template qui a été rendu dans le DOM final.

NB : La balise <ng-template> n'apparait pas dans le DOM final non plus.

Conclusion

Voilà c'est tout pour le <ng-container>, n’hésitez pas à laisser un commentaire, en espérant que cela vous a plu !

Sources

Téléchargez votre Starter Kit Angular

Starter Kit Angular

En souscrivant vous recevrez :

  • Une roadmap d'un développeur Angular
  • Un cookbook Angular des commandes les plus utiles
  • Un extrait de formation

100% gratuit.

Auteur

image auteur
Lucas BENTO-VERSACE Alternant chez Codewise / Étudiant en développement web lucas.bentoversace@ynov.com
"Alternant chez Codewise, passioné par l'informatique et les technologies depuis mon plus jeune âge. J'ai découvert le monde du web et depuis je ne m'en lasse pas ! Fan de jeux vidéos, de sports et de musiques. "