Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a if-else Angular template with only ng-container?

I would like to make an if-else statement in my angular template. I started with that :

<ng-container *ngIf="contributeur.deb; else newDeb" >
    [... HERE IS A RESULT 1]
</ng-container>
<ng-template #newDeb>
    [... HERE IS A RESULT 2]
</ng-template>

And I tried to only use ng-container :

<ng-container *ngIf="contributeur.deb; else newDeb" >
    [... HERE IS A RESULT 1]
</ng-container>
<ng-container #newDeb>
    [... HERE IS A RESULT 2]
</ng-container >

Unfortunately, this does not work. I have this error :

ERROR TypeError: templateRef.createEmbeddedView is not a function
    at ViewContainerRef_.createEmbeddedView (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:10200:52)
    at NgIf._updateView (eval at <anonymous> (vendor.bundle.js:96), <anonymous>:2013:45)
    at NgIf.set [as ngIfElse] (eval at <anonymous> (vendor.bundle.js:96), <anonymous>:1988:18)
    at updateProp (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:11172:37)
    at checkAndUpdateDirectiveInline (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:10873:19)
    at checkAndUpdateNodeInline (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:12290:17)
    at checkAndUpdateNode (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:12258:16)
    at debugCheckAndUpdateNode (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:12887:59)
    at debugCheckDirectivesFn (eval at <anonymous> (vendor.bundle.js:11), <anonymous>:12828:13)
    at Object.eval [as updateDirectives] (ActionsButtons.html:5)

Can anyone explain me what is going wrong in this code ?

like image 778
Thomas Betous Avatar asked May 31 '17 14:05

Thomas Betous


People also ask

Can we apply ngIf to ng-template?

Alternatively, (and preferably), you can also use the ng-template element by prefixing an asterisk (*), which is the shorthand syntax. For instance, *ngIf, *ngFor. These directives are very common in Angular, and are present almost everywhere either implicitly or explicitly.

Can we use ng-template inside Ng-container?

To sum up, ng-content is used to display children in a template, ng-container is used as a non-rendered container to avoid having to add a span or a div, and ng-template allows you to group some content that is not rendered directly but can be used in other places of your template or you code.

Can we add ngIf to Ng-container?

So ng-container is useful when you want to conditionaly append a group of elements (ie using *ngIf="foo" ) in your application but don't want to wrap them with another element. That's a good point. I guess that it differs from <template> when it's used without directives. <template> would just produce <!


3 Answers

The code for the ngIf directive expects to be passed a reference to a template (TemplateRef) for the else branch, which it will call createEmbeddedView on to display the nested content. Therefore, it makes no sense to try to use any other kind of element for the else content - it just won't work. You're able to nest an ng-container inside the ng-template if needs be, though.

This might seem unintuitive, but bear in mind that structural directives (i.e. ones that you call with a *) are always represented as ng-template under the hood, no matter what kind of element they're attached to - these two pieces of code are the same:

<ng-container *ngIf="contributeur.deb; else newDeb" >
    ...
</ng-container>
<ng-template #newDeb>
    ...
</ng-template>

<ng-template [ngIf]="contributeur.deb; else newDeb">
    <ng-container>
        ...
    </ng-container>
</ng-template>
<ng-template #newDeb>
    ...
</ng-template>
like image 113
Joe Clay Avatar answered Oct 21 '22 23:10

Joe Clay


I do not love the standard Angular structure for if then else. Then I found an alternative solution with ngSwitch:

<ng-container [ngSwitch]="isFirstChoice(foo) ? 1 : (isSecondChoice(foo) ? 2 : -1)">
  <ng-container *ngSwitchCase="1">
    ...first choice...
  </ng-container>
  <ng-container *ngSwitchCase="2">
    ...second choice...
  </ng-container>
  <ng-container *ngSwitchDefault>
    ...another choice...
  </ng-container>
</ng-container>

To answer to your request I'd use this:

<ng-container [ngSwitch]="contributeur.deb && 'isDeb'">
  <ng-container *ngSwitchCase="'isDeb'">
    ......
  </ng-container>
  <ng-container *ngSwitchDefault>
    ......
  </ng-container>
</ng-container>
like image 16
riofly Avatar answered Oct 22 '22 00:10

riofly


It bears mentioning that this simple alternative is perhaps more readable than many of the other options. Just using a second ng-container, and just 'not'-ing the condition with an exclamation mark to make the else section.

<ng-container *ngIf="contributeur.deb" >
    [... HERE IS A RESULT 1]
</ng-container>
<ng-container *ngIf="!contributeur.deb">
    [... HERE IS A RESULT 2]
</ng-container >
like image 3
Adam Wise Avatar answered Oct 21 '22 23:10

Adam Wise