NgIf
directive
Conditionally includes a template based on the value of an expression.
NgModule
Selectors
[ngIf]
Properties
| Property | Description |
|---|---|
@Input()ngIf: any | Write-only. |
@Input()ngIfThen: TemplateRef<NgIfContext> | null | Write-only. |
@Input()ngIfElse: TemplateRef<NgIfContext> | null | Write-only. |
Description
ngIf evaluates the expression and then renders the then or else template in its place when expression is truthy or falsy respectively. Typically the:
-
thentemplate is the inline template ofngIfunless bound to a different value. -
elsetemplate is blank unless it is bound.
Most common usage
The most common usage of the ngIf directive is to conditionally show the inline template as seen in this example:
@Component({
selector: 'ng-if-simple',
template: `
<button (click)="show = !show">{{show ? 'hide' : 'show'}}</button>
show = {{show}}
<br>
<div *ngIf="show">Text to show</div>
`
})
class NgIfSimple {
show: boolean = true;
} Showing an alternative template using else
If it is necessary to display a template when the expression is falsy use the else template binding as shown. Note that the else binding points to a <ng-template> labeled #elseBlock. The template can be defined anywhere in the component view but is typically placed right after ngIf for readability.
@Component({
selector: 'ng-if-else',
template: `
<button (click)="show = !show">{{show ? 'hide' : 'show'}}</button>
show = {{show}}
<br>
<div *ngIf="show; else elseBlock">Text to show</div>
<ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>
`
})
class NgIfElse {
show: boolean = true;
} Using non-inlined then template
Usually the then template is the inlined template of the ngIf, but it can be changed using a binding (just like else). Because then and else are bindings, the template references can change at runtime as shown in this example.
@Component({
selector: 'ng-if-then-else',
template: `
<button (click)="show = !show">{{show ? 'hide' : 'show'}}</button>
<button (click)="switchPrimary()">Switch Primary</button>
show = {{show}}
<br>
<div *ngIf="show; then thenBlock; else elseBlock">this is ignored</div>
<ng-template #primaryBlock>Primary text to show</ng-template>
<ng-template #secondaryBlock>Secondary text to show</ng-template>
<ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>
`
})
class NgIfThenElse implements OnInit {
thenBlock: TemplateRef<any>|null = null;
show: boolean = true;
@ViewChild('primaryBlock')
primaryBlock: TemplateRef<any>|null = null;
@ViewChild('secondaryBlock')
secondaryBlock: TemplateRef<any>|null = null;
switchPrimary() {
this.thenBlock = this.thenBlock === this.primaryBlock ? this.secondaryBlock : this.primaryBlock;
}
ngOnInit() { this.thenBlock = this.primaryBlock; }
} Storing conditional result in a variable
A common pattern is that we need to show a set of properties from the same object. If the object is undefined, then we have to use the safe-traversal-operator ?. to guard against dereferencing a null value. This is especially the case when waiting on async data such as when using the async pipe as shown in following example:
Hello {{ (userStream|async)?.last }}, {{ (userStream|async)?.first }}! There are several inefficiencies in the above example:
- We create multiple subscriptions on
userStream. One for eachasyncpipe, or two in the example above. - We cannot display an alternative screen while waiting for the data to arrive asynchronously.
- We have to use the safe-traversal-operator
?.to access properties, which is cumbersome. - We have to place the
asyncpipe in parenthesis.
A better way to do this is to use ngIf and store the result of the condition in a local variable as shown in the the example below:
@Component({
selector: 'ng-if-let',
template: `
<button (click)="nextUser()">Next User</button>
<br>
<div *ngIf="userObservable | async as user; else loading">
Hello {{user.last}}, {{user.first}}!
</div>
<ng-template #loading let-user>Waiting... (user is {{user|json}})</ng-template>
`
})
class NgIfAs {
userObservable = new Subject<{first: string, last: string}>();
first = ['John', 'Mike', 'Mary', 'Bob'];
firstIndex = 0;
last = ['Smith', 'Novotny', 'Angular'];
lastIndex = 0;
nextUser() {
let first = this.first[this.firstIndex++];
if (this.firstIndex >= this.first.length) this.firstIndex = 0;
let last = this.last[this.lastIndex++];
if (this.lastIndex >= this.last.length) this.lastIndex = 0;
this.userObservable.next({first, last});
}
} Notice that:
- We use only one
asyncpipe and hence only one subscription gets created. -
ngIfstores the result of theuserStream|asyncin the local variableuser. - The local
usercan then be bound repeatedly in a more efficient way. - No need to use the safe-traversal-operator
?.to access properties asngIfwill only display the data ifuserStreamreturns a value. - We can display an alternative template while waiting for the data.
Syntax
Simple form:
Form with an else block:
<div *ngIf="condition; else elseBlock">...</div> <ng-template #elseBlock>...</ng-template>
Form with a then and else block:
<div *ngIf="condition; then thenBlock else elseBlock"></div> <ng-template #thenBlock>...</ng-template> <ng-template #elseBlock>...</ng-template>
Form with storing the value locally:
<div *ngIf="condition as value; else elseBlock">{{value}}</div>
<ng-template #elseBlock>...</ng-template>
© 2010–2019 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://v6.angular.io/api/common/NgIf