class NgIf { constructor(_viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext>) ngIf ngIfThen ngIfElse }
[ngIf]
Conditionally includes a template based on the value of an expression
.
ngIf
evaluates the expression
and then renders the then
or else
template in its place when expression is truthy or falsy respectively. Typically the:
then
template is the inline template of ngIf
unless bound to a different value.else
template is blank unless it is bound.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; }
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; }
then
templateUsually 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; show: boolean = true; @ViewChild('primaryBlock') primaryBlock: TemplateRef<any> = null; @ViewChild('secondaryBlock') secondaryBlock: TemplateRef<any> = null; switchPrimary() { this.thenBlock = this.thenBlock === this.primaryBlock ? this.secondaryBlock : this.primaryBlock; } ngOnInit() { this.thenBlock = this.primaryBlock; } }
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 folowing example:
Hello {{ (userStream|async)?.last }}, {{ (userStream|async)?.first }}!
There are several inefficiencies in the above example:
userStream
. One for each async
pipe, or two in the example above.?.
to access properties, which is cumbersome.async
pipe 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:
async
pipe and hence only one subscription gets created.ngIf
stores the result of the userStream|async
in the local variable user
.user
can then be bound repeatedly in a more efficient way.?.
to access properties as ngIf
will only display the data if userStream
returns a value.Simple form:
<div *ngIf="condition">...</div>
<div template="ngIf condition">...</div>
<ng-template [ngIf]="condition"><div>...</div></ng-template>
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>
constructor(_viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext>)
ngIf
ngIfThen
ngIfElse
exported from common/index, defined in common/src/directives/ng_if.ts
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://angular.io/docs/ts/latest/api/common/index/NgIf-directive.html