'*ngIf else if in template

How would I have multiple cases in an *ngIf statement? I'm used to Vue or Angular 1 with having an if, else if, and else, but it seems like Angular 4 only has a true (if) and false (else) condition.

According to the documentation, I can only do:

<ng-container *ngIf="foo === 1; then first else second"></ng-container>
<ng-template #first>First</ng-template>
<ng-template #second>Second</ng-template>
<ng-template #third>Third</ng-template>

But I want to have multiple conditions (something like):

<ng-container *ngIf="foo === 1; then first; foo === 2; then second else third"></ng-container>
<ng-template #first>First</ng-template>
<ng-template #second>Second</ng-template>
<ng-template #third>Third</ng-template>

But I'm ending up having to use ngSwitch, which feels like a hack:

<ng-container [ngSwitch]="true">
  <div *ngSwitchCase="foo === 1">First</div>
  <div *ngSwitchCase="bar === 2">Second</div>
  <div *ngSwitchDefault>Third</div>
</ng-container>

Alternately, it seems like a lot of the syntaxes I've got used to from Angular 1 and Vue aren't supported in Angular 4, so what would be the recommended way to structure my code with conditions like this?



Solution 1:[1]

You can just use:

<ng-template [ngIf]="index == 1">First</ng-template>
<ng-template [ngIf]="index == 2">Second</ng-template>
<ng-template [ngIf]="index == 3">Third</ng-template>

unless the ng-container part is important to your design I suppose.

Here's a Plunker

Solution 2:[2]

This seems to be the cleanest way to do

if (foo === 1) {

} else if (bar === 99) {

} else if (foo === 2) {

} else {

}

in the template:

<ng-container *ngIf="foo === 1; else elseif1">foo === 1</ng-container>
<ng-template #elseif1>
    <ng-container *ngIf="bar === 99; else elseif2">bar === 99</ng-container>
</ng-template>
<ng-template #elseif2>
    <ng-container *ngIf="foo === 2; else else1">foo === 2</ng-container>
</ng-template>
<ng-template #else1>else</ng-template>

Notice that it works like a proper else if statement should when the conditions involve different variables (only 1 case is true at a time). Some of the other answers don't work right in such a case.

aside: gosh angular, that's some really ugly else if template code...

Solution 3:[3]

You can use multiple way based on sitaution:

  1. If you Variable is limited to specific Number or String, best way is using ngSwitch or ngIf:

    <!-- foo = 3 -->
    <div [ngSwitch]="foo">
        <div *ngSwitchCase="1">First Number</div>
        <div *ngSwitchCase="2">Second Number</div>
        <div *ngSwitchCase="3">Third Number</div>
        <div *ngSwitchDefault>Other Number</div>
    </div>
    
    <!-- foo = 3 -->
    <ng-template [ngIf]="foo === 1">First Number</ng-template>
    <ng-template [ngIf]="foo === 2">Second Number</ng-template>
    <ng-template [ngIf]="foo === 3">Third Number</ng-template>
    
    
    <!-- foo = 'David' -->
    <div [ngSwitch]="foo">
        <div *ngSwitchCase="'Daniel'">Daniel String</div>
        <div *ngSwitchCase="'David'">David String</div>
        <div *ngSwitchCase="'Alex'">Alex String</div>
        <div *ngSwitchDefault>Other String</div>
    </div>
    
    <!-- foo = 'David' -->
    <ng-template [ngIf]="foo === 'Alex'">Alex String</ng-template>
    <ng-template [ngIf]="foo === 'David'">David String</ng-template>
    <ng-template [ngIf]="foo === 'Daniel'">Daniel String</ng-template>
    
  2. Above not suitable for if elseif else codes and dynamic codes, you can use below code:

    <!-- foo = 5 -->
    <ng-container *ngIf="foo >= 1 && foo <= 3; then t13"></ng-container>
    <ng-container *ngIf="foo >= 4 && foo <= 6; then t46"></ng-container>
    <ng-container *ngIf="foo >= 7; then t7"></ng-container>
    
    <!-- If Statement -->
    <ng-template #t13>
        Template for foo between 1 and 3
    </ng-template>
    <!-- If Else Statement -->
    <ng-template #t46>
        Template for foo between 4 and 6
    </ng-template>
    <!-- Else Statement -->
    <ng-template #t7>
        Template for foo greater than 7
    </ng-template>
    

Note: You can choose any format, but notice every code has own problems

Solution 4:[4]

To avoid nesting and ngSwitch, there is also this possibility, which leverages the way logical operators work in Javascript:

<ng-container *ngIf="foo === 1; then first; else (foo === 2 && second) || (foo === 3 && third)"></ng-container>
  <ng-template #first>First</ng-template>
  <ng-template #second>Second</ng-template>
  <ng-template #third>Third</ng-template>

Solution 5:[5]

Or maybe just use conditional chains with ternary operator. if … else if?… else if … else chain.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator#Conditional_chains

<ng-container [ngTemplateOutlet]="isFirst ? first : isSecond ? second : third"></ng-container>

<ng-template #first></ng-template>
<ng-template #second></ng-template>
<ng-template #third></ng-template>

I like this aproach better.

Solution 6:[6]

you don't need to use *ngIf if you use ng-container

<ng-container [ngTemplateOutlet]="myTemplate === 'first' ? first : myTemplate === 
   'second' ? second : third"></ng-container>

  <ng-template #first>first</ng-template>
  <ng-template #second>second</ng-template>
  <ng-template #third>third</ng-template>

Solution 7:[7]

<ion-row *ngIf="cat === 1;else second"></ion-row>
<ng-template #second>
    <ion-row *ngIf="cat === 2;else third"></ion-row>
</ng-template>
<ng-template #third>

</ng-template>

Angular is already using ng-template under the hood in many of the structural directives that we use all the time: ngIf, ngFor and ngSwitch.

> What is ng-template in Angular

https://www.angularjswiki.com/angular/what-is-ng-template-in-angular/

Solution 8:[8]

I came a cross this type of situation *ngIf elseIf else and I solved using ng-template, Hope the following snippet may depicts briefly,

I have a form control named "NIC" and need to show one error message at a time when the form control invalid.

form: FormGroup = new FormGroup({
    NIC: new FormControl('', [Validators.required, Validators.minLength(10), Validators.maxLength(10), Validators.pattern("^[0-9]*$")])
  });

Template

<mat-form-field appearance="standard">
    <mat-label>NIC Number</mat-label>
    <input matInput placeholder="Enter NIC no" formControlName="NIC">
    <mat-error *ngIf="form.controls['NIC'].errors?.required; else minvalue">This field is mandatory.
    </mat-error>

    <ng-template #minvalue>
        <mat-error *ngIf="form.controls['NIC'].errors?.minlength; else maxvalue">Minimum 10 charactors
            needed.
        </mat-error>
    </ng-template>

    <ng-template #maxvalue>
        <mat-error *ngIf="form.controls['NIC'].errors?.maxLength; else numericonly">Maximum 10
            charactors allowed.
        </mat-error>
    </ng-template>

    <ng-template #numericonly>
        <mat-error *ngIf="form.controls['NIC'].errors?.pattern">
            Numeric characters only.
        </mat-error>
    </ng-template>

</mat-form-field>

Solution 9:[9]

You can also use this old trick for converting complex if/then/else blocks into a slightly cleaner switch statement:

<div [ngSwitch]="true">
    <button (click)="foo=(++foo%3)+1">Switch!</button>

    <div *ngSwitchCase="foo === 1">one</div>
    <div *ngSwitchCase="foo === 2">two</div>
    <div *ngSwitchCase="foo === 3">three</div>
</div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dylan
Solution 2
Solution 3
Solution 4 Max21
Solution 5
Solution 6 nicolas
Solution 7
Solution 8 Azad
Solution 9 Michael Payne