<ng-container> vs <template>

150

ng-container est mentionné dans la documentation Angular 2 mais il n'y a aucune explication sur son fonctionnement et quels sont les cas d'utilisation.

Il est notamment mentionné dans les directives ngPluralet ngSwitch.

Est- <ng-container>ce que cela fait la même chose que <template>, ou cela dépend si une directive a été écrite pour utiliser l'un d'entre eux?

Sont

<ng-container *ngPluralCase="'=0'">there is nothing</ng-container>

et

<template [ngPluralCase]="'=0'">there is nothing</template>

censé être le même?

Comment choisissons-nous l'un d'entre eux?

Comment peut-il <ng-container>être utilisé dans une directive personnalisée?

Fiole d'Estus
la source

Réponses:

244

Edit: Maintenant, il est documenté

<ng-container> à la rescousse

Angular  <ng-container> 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.

(...)

Le  <ng-container> est un élément de syntaxe reconnu par l'analyseur angulaire. Ce n'est pas une directive, un composant, une classe ou une interface. C'est plus comme les accolades dans un bloc if JavaScript:

  if (someCondition) {
      statement1; 
      statement2;
      statement3;
     }

Sans ces accolades, JavaScript n'exécuterait la première instruction que lorsque vous avez l'intention de les exécuter toutes sous forme d'un seul bloc. Le  <ng-container> répond à un besoin similaire dans les modèles angulaires.

Réponse originale:

Selon cette pull request :

<ng-container> est un conteneur logique qui peut être utilisé pour regrouper des nœuds mais qui n'est pas rendu dans l'arborescence DOM en tant que nœud.

<ng-container> est rendu sous forme de commentaire HTML.

donc ce gabarit angulaire:

<div>
    <ng-container>foo</ng-container>
<div>

produira ce type de sortie:

<div>
    <!--template bindings={}-->foo
<div>

C'est donc ng-containerutile lorsque vous souhaitez ajouter conditionnellement un groupe d'éléments (c'est-à-dire en utilisant *ngIf="foo") dans votre application mais que vous ne voulez pas les envelopper avec un autre élément .

<div>
    <ng-container *ngIf="true">
        <h2>Title</h2>
        <div>Content</div>
    </ng-container>
</div>

produira alors:

<div>
    <h2>Title</h2>
    <div>Content</div>
</div>
n00dl3
la source
C'est un bon point. Je suppose que cela diffère de <template>quand il est utilisé sans directives. <template>produirait juste <!--template bindings={}-->dans ce cas.
Estus Flask
en fait, <template></template>produira <script></script> voir ceci
n00dl3
Ce n'était pas le cas dans mon cas. Même s'il y en a <script>lors de la compilation, il est supprimé par la suite, il n'y a pas de balises supplémentaires dans le DOM. Je pense que le manuel contient des informations obsolètes ou est tout simplement erroné à ce sujet. Quoi qu'il en soit, merci d'avoir indiqué la principale différence entre <ng-container> et <template>.
Estus Flask
Avant la sortie, Angular a rendu <script></script>. Il rend quelque chose comme ça <!--template bindings={}-->depuis un bon moment. Les documents seront bientôt corrigés.
Quartier
40

La documentation ( https://angular.io/guide/template-syntax#!#star-template ) donne l'exemple suivant. Disons que nous avons un code de modèle comme celui-ci:

<hero-detail *ngIf="currentHero" [hero]="currentHero"></hero-detail>

Avant qu'il ne soit rendu, il sera "désucléé". Autrement dit, la notation astérisque sera transcrite en notation:

<template [ngIf]="currentHero">
  <hero-detail [hero]="currentHero"></hero-detail>
</template>

Si 'currentHero' est vrai, cela sera rendu comme

<hero-detail> [...] </hero-detail>

Mais que faire si vous voulez une sortie conditionnelle comme celle-ci:

<h1>Title</h1><br>
<p>text</p>

.. et vous ne voulez pas que la sortie soit enveloppée dans un conteneur.

Vous pouvez écrire la version déshydratée directement comme ceci:

<template [ngIf]="showContent">
  <h1>Title</h1>
  <p>text</p><br>
</template>

Et cela fonctionnera très bien. Cependant, maintenant nous avons besoin de ngIf pour avoir des crochets [] au lieu d'un astérisque *, et c'est déroutant ( https://github.com/angular/angular.io/issues/2303 )

Pour cette raison, une notation différente a été créée, comme ceci:

<ng-container *ngIf="showContent"><br>
  <h1>Title</h1><br>
  <p>text</p><br>
</ng-container>

Les deux versions produiront les mêmes résultats (seules les balises h1 et p seront rendues). Le second est préféré car vous pouvez utiliser * ngIf comme toujours.

Carlo Roosen
la source
Belle explication, cela donne un aperçu de Comment l' ng-containeridée directive est venue , merci :)
Pankaj Parkar
0

Les cas d'utilisation d'IMO ng-containersont de simples remplacements pour lesquels un modèle / composant personnalisé serait excessif. Dans le document de l'API, ils mentionnent ce qui suit

utiliser un ng-container pour regrouper plusieurs nœuds racine

et je suppose que c'est de ça qu'il s'agit: regrouper des choses.

Sachez que la ng-containerdirective tombe au lieu d'un modèle où sa directive enveloppe le contenu réel.

Mat
la source
Avez-vous un lien vers cette mention? Ne le voyant utilisé que dans la documentation liée ci-dessus et la documentation de cas pluriel pour le moment: angular.io/docs/ts/latest/api/common/index/… .
Koslun
1
Merci, créé un problème sur le site de documentation concernant le manque de documentation et référencé cette réponse: github.com/angular/angular.io/issues/2553
Koslun
1
a voté à la baisse -1. ng-container ne consiste pas à éviter un modèle personnalisé, il s'agit de pouvoir avoir un contenu conditionnel qui n'est pas enveloppé dans un conteneur. En fait, un modèle personnalisé introduira également un conteneur wrapper, à savoir la balise directive elle-même.
Carlo Roosen
1
Tu as tout à fait raison. C'est certainement une différence qui doit être mentionnée. J'ai ajouté l'indice à mon message.
Matt
-1

Un cas d'utilisation pour cela lorsque vous voulez utiliser une table avec * ngIf et * ngFor - Car mettre un div dans td / th entraînera un mauvais comportement de l'élément table -. Je fait face à ce problème et qui était la réponse.

shakram02
la source
1
Mais la même chose peut être réalisée avec <template [ngIf]...>. La question était la différence entre ces deux approches.
Estus Flask
oh, mon mauvais, il semble y avoir une réponse ici stackoverflow.com/questions/40529537/… ils disent simplement que c'est juste une différence de syntaxe
shakram02