Tout ce que vous devez savoir sur ng-template, ng-content, ng-container et * ngTemplateOutlet dans Angular

C'était un de ces jours où j'étais occupé à travailler sur de nouvelles fonctionnalités pour mon projet de bureau. Tout à coup, quelque chose a attiré mon attention:

En inspectant le DOM, j'ai vu l' ngcontentapplication sur des éléments par Angular. Hmm… s'ils contiennent les éléments du DOM final, à quoi sert-il ? À ce moment-là, je me suis confondu entre et .

Dans la quête de connaître les réponses à mes questions, j'ai découvert le concept de . À ma grande surprise, il y en avait aussi *ngTemplateOutlet. J'ai commencé mon voyage à la recherche de clarté sur deux concepts, mais maintenant j'en avais quatre, qui sonnaient presque de la même manière!

Avez-vous déjà été dans cette situation? Si oui, alors vous êtes au bon endroit. Alors sans plus tarder, prenons-les un par un.

1.

Comme son nom l' indique le est un élément de modèle qui utilise angulaire directives structurelles ( *ngIf, *ngFor, [ngSwitch]et directives sur mesure).

Ces éléments de modèle ne fonctionnent qu'en présence de directives structurelles . Angular enveloppe l'élément hôte (auquel la directive est appliquée) à l'intérieuret consomme ledans le DOM terminé en le remplaçant par des commentaires de diagnostic.

Prenons un exemple simple de *ngIf:

Ci-dessus, l'interprétation angulaire de *ngIf. Angular place l'élément hôte auquel la directive est appliquée et conserve l'hôte tel quel. Le DOM final est similaire à ce que nous avons vu au début de cet article:

Usage:

Nous avons vu comment Angular l'utilise mais que se passe-t-il si nous voulons l'utiliser? Comme ces éléments ne fonctionnent qu'avec une directive structurelle, nous pouvons écrire comme suit:

Voici homeune booleanpropriété du composant définie sur truevalue. La sortie du code ci-dessus dans DOM:

Rien n'a été rendu! :(

Mais pourquoi ne pouvons-nous pas voir notre message même après une utilisation correcte avec une directive structurelle?

C'était le résultat attendu. Comme nous l'avons déjà mentionné, Angular remplace le par des commentaires de diagnostic. Nul doute que le code ci-dessus ne générerait aucune erreur, car Angular convient parfaitement à votre cas d'utilisation. Vous ne sauriez jamais ce qui s'est passé exactement dans les coulisses.

Comparons les deux DOM ci-dessus qui ont été rendus par Angular:

Si vous regardez attentivement, il y a une balise de commentaire supplémentaire dans le DOM final de l' exemple 2 . Le code interprété par Angular était:

Angular a enveloppé votre hôte dans un autre et a converti non seulement les commentaires externes en commentaires de diagnostic, mais également les commentaires internes! C'est pourquoi vous ne pouvez voir aucun de vos messages.

Pour se débarrasser de cela, il existe deux façons d'obtenir le résultat souhaité:

Méthode 1:

Dans cette méthode, vous fournissez à Angular le format déshydraté qui ne nécessite aucun traitement supplémentaire. Cette fois, Angular ne serait converti qu'en commentaires mais laisse le contenu à l'intérieur intact (ils ne sont plus à l'intérieur comme dans le cas précédent). Ainsi, il rendra le contenu correctement.

Pour en savoir plus sur l'utilisation de ce format avec d'autres directives structurelles, reportez-vous à cet article.

Méthode 2:

C'est un format assez invisible et rarement utilisé (en utilisant deux frères et soeurs ). Ici, nous donnons une référence de modèle au *ngIfdans son thenpour lui dire quel modèle doit être utilisé si la condition est vraie.

Utiliser plusieurs comme celui-ci n'est pas conseillé (vous pouvez utiliser à la place) car ce n'est pas ce à quoi ils sont destinés. Ils sont utilisés comme conteneur de modèles qui peuvent être réutilisés à plusieurs endroits. Nous en parlerons plus en détail dans une section ultérieure de cet article.

2.

Avez-vous déjà écrit ou vu du code ressemblant à ceci:

La raison pour laquelle nous sommes nombreux à écrire ce code est l'incapacité d'utiliser plusieurs directives structurelles sur un seul élément hôte dans Angular. Maintenant, ce code fonctionne bien mais il introduit plusieurs vides supplémentaires dans le DOM s'il item.ids'agit d'une valeur falsifiée qui pourrait ne pas être requise.

On ne peut pas être concerné par un exemple simple comme celui-ci, mais pour une énorme application qui a un DOM complexe (pour afficher des dizaines de milliers de données), cela pourrait devenir gênant car les éléments pourraient avoir des écouteurs qui seront toujours là DOM écoute les événements.

Ce qui est encore pire, c'est le niveau d'imbrication que vous devez faire pour appliquer votre style (CSS)!

Pas de soucis, nous devons à la rescousse!

L'Angular est un élément de regroupement qui n'interfère pas avec les styles ou la mise en page car Angular ne le met pas dans le DOM .

Donc, si nous écrivons notre exemple 1 avec :

Nous obtenons le DOM final sous la forme:

Voyez, nous nous sommes débarrassés de ces s vides . Nous devrions utiliser lorsque nous voulons simplement appliquer plusieurs directives structurelles sans introduire d'élément supplémentaire dans notre DOM.

Pour plus d'informations, reportez-vous à la documentation. Il existe un autre cas d'utilisation où il est utilisé pour injecter dynamiquement un modèle dans une page. Je couvrirai ce cas d'utilisation dans la dernière section de cet article.

3.

Ils sont utilisés pour créer des composants configurables. Cela signifie que les composants peuvent être configurés en fonction des besoins de son utilisateur. Ceci est bien connu sous le nom de projection de contenu . Les composants qui sont utilisés dans les bibliothèques publiées utilisent pour se rendre configurables.

Considérez un composant simple :

Le contenu HTML passé entre les balises d'ouverture et de fermeture du composant est le contenu à projeter. C'est ce que nous appelons la projection de contenu . Le contenu sera rendu à l' intérieur du composant. Cela permet au consommateur du composant de passer n'importe quel pied de page personnalisé dans le composant et de contrôler exactement comment il souhaite qu'il soit rendu.

Projections multiples:

Et si vous pouviez décider quel contenu doit être placé où? Au lieu de chaque contenu projeté à l'intérieur d'un seul , vous pouvez également contrôler la façon dont le contenu sera projeté avec l' selectattribut de . Il faut un sélecteur d'élément pour décider quel contenu projeter à l'intérieur d'un particulier .

Voici comment:

Nous avons modifié la définition pour effectuer une projection multi-contenu. L' selectattribut sélectionne le type de contenu qui sera rendu à l'intérieur d'un particulier . Ici, nous devons d'abord selectrendre l' h1élément d'en- tête . Si le contenu projeté n'a aucun h1élément, il ne rendra rien. De même, le second selectrecherche un div. Le reste du contenu est rendu dans le dernier sans select.

L'appel du composant ressemblera à ceci:

4. * ngTemplateOutlet

… Ils sont utilisés comme conteneur de modèles qui peuvent être réutilisés à plusieurs endroits. Nous en couvrirons plus à ce sujet dans une section ultérieure de cet article.

… Il existe un autre cas d'utilisation où il est utilisé pour injecter dynamiquement un modèle dans une page. Je couvrirai ce cas d'utilisation dans la dernière section de cet article.

C'est la section où nous discuterons des deux points ci-dessus mentionnés précédemment. *ngTemplateOutletest utilisé pour deux scénarios - pour insérer un modèle commun dans diverses sections d'une vue indépendamment des boucles ou des conditions et pour créer un composant hautement configuré.

Réutilisation du modèle:

Considérez une vue dans laquelle vous devez insérer un modèle à plusieurs endroits. Par exemple, un logo d'entreprise à placer dans un site Web. Nous pouvons y parvenir en écrivant une fois le modèle du logo et en le réutilisant partout dans la vue.

Voici l'extrait de code:

Comme vous pouvez le voir, nous venons d'écrire le modèle de logo une fois et de l'utiliser trois fois sur la même page avec une seule ligne de code!

*ngTemplateOutletaccepte également un objet de contexte qui peut être passé pour personnaliser la sortie du modèle commun. Pour plus d'informations sur l'objet de contexte, reportez-vous à la documentation officielle.

Composants personnalisables:

Le deuxième cas d'utilisation concerne *ngTemplateOutletles composants hautement personnalisés. Considérez notre exemple précédent de composant avec quelques modifications:

Au- dessus est la version modifiée du composant qui accepte trois propriétés d'entrée -  headerTemplate, bodyTemplate, footerTemplate. Voici l'extrait de project-content.ts:

Ce que nous essayons de réaliser ici, c'est d'afficher l'en-tête, le corps et le pied de page reçus du composant parent de . Si l'un d'entre eux n'est pas fourni, notre composant affichera le modèle par défaut à sa place. Ainsi, créer un composant hautement personnalisé.

Pour utiliser notre composant récemment modifié:

C'est ainsi que nous allons transmettre les références de modèle à notre composant. Si l'un d'entre eux n'est pas passé, le composant rendra le modèle par défaut.

ng-content contre * ngTemplateOutlet

Ils nous aident tous les deux à réaliser des composants hautement personnalisés, mais lesquels choisir et quand?

On peut clairement voir que cela *ngTemplateOutletnous donne plus de puissance pour afficher le modèle par défaut si aucun n'est fourni.

Ce n'est pas le cas avec ng-content. Il rend le contenu tel quel. Au maximum, vous pouvez diviser le contenu et le rendre à différents endroits de votre vue à l'aide de l' selectattribut. Vous ne pouvez pas rendre conditionnellement le contenu à l'intérieur ng-content. Vous devez montrer le contenu qui est reçu du parent sans aucun moyen de prendre des décisions basées sur le contenu.

Cependant, le choix de choisir parmi les deux dépend complètement de votre cas d'utilisation. Au moins maintenant, nous avons une nouvelle arme *ngTemplateOutletdans notre arsenal qui offre plus de contrôle sur le contenu en plus des fonctionnalités de ng-content!