Tuesday, August 3, 2021

ng-template in Angular

In this tutorial we’ll learn in detail about <ng-template> element in Angular.


Using ng-template

Using <ng-template> element in Angular you can define a template that doesn't render anything by default. Here note that it "only defines a template". That gives you control over how the content is displayed.

For example if you just wrap some elements in an <ng-template> without using any structural directive or some other way to display those wrapped elements, those elements disappear.

<p>Using ng-template here</p>
<ng-template>
    <p>This text is not displayed</p>
</ng-template>

The above code will display only-

Using ng-template here

<p> element wrapped within <ng-template> is not displayed.

Now we’ll see how <ng-template> is already used by many built-in structural directives in Angular. We’ll also see how to use <ng-template> in conjunction with ngTemplateOutlet and with TemplateRef to render the wrapped elements.

ng-template with Angular structural directives

Angular lets us write structural directives in a short form which are internally translated into the normal binding syntax where ng-template element wraps the host element (element where structural directive *ngIf, *ngFor is used)

ng-template and ngIf

If you have used *ngIf as given below

<div *ngIf="user">{{user.name}}</div>

Where the logic is; display the user name if user object exists.

Internally Angular translates the above statement as given below.

<ng-template [ngIf]="user">
  <div>{{user.name}}</div>
</ng-template>

As you can see the *ngIf directive moves to the <ng-template> where it becomes a property binding in square brackets, [ngIf]. The rest of the <div> moves inside the <ng-template>. This should give you an idea how <ng-template> is used with a structural directive to give you control over how the content is displayed.

ng-template and ngFor

Structural directive *ngFor is the shorthand form which is internally expanded into a long form that uses the ngForOf selector on an <ng-template> element.

For example if *ngFor is used with in the host element <tr> as given below.

<tr *ngFor="let user of users; let i=index ">
  <td>{{user.name}}</td>
  <td>{{user.age}}</td>
</tr>

Angular under the hood translates it into the following form

<ng-template ngFor let-user [ngForOf]="users" let-i="index" >
  <tr>
    <td>{{user.name}}</td>
    <td>{{user.age}}</td>
  </tr>
</ng-template>

ng-template and ngSwitch

If you use ngSwitch structural directive as given below

<div [ngSwitch]="getSize()">
  <span *ngSwitchCase="0">No number is added</span>
  <span *ngSwitchCase="1">One number is added</span>
  <span *ngSwitchCase="2">Two numbers are added</span>
  <span *ngSwitchCase="3">Three numbers are added</span>
  <span *ngSwitchDefault>More than three numbers are added</span>
</div>

Internally it is translated into the following form moving *ngSwitchCase to the <ng-template> where it becomes a property binding in square brackets, [ngSwitchCase].

<div [ngSwitch]="getSize()">
  <ng-template [ngSwitchCase]="0">
    <span>No number is added</span>
  </ng-template>
  <ng-template [ngSwitchCase]="1">
    <span>One number is added</span>
  </ng-template>
  <ng-template [ngSwitchCase]="2">
    <span>Two numbers are added</span>
  </ng-template>
  <ng-template [ngSwitchCase]="3">
    <span>Three numbers are added</span>
  </ng-template>
  <ng-template ngSwitchDefault>
    <span>More than three numbers are added</span>
  </ng-template>
</div>

ngIf with else to show alternate template

In all the above usage of structural directives as you can see ng-template is used internally but if you have ever used ngIf with else that’s where you can actually use ng-template explicitly.

<div *ngIf="show; else elseBlock">This text is displayed when condition is true</div>
<ng-template #elseBlock>This text is displayed when condition is false.</ng-template>

Here an else template binding is used which points to an <ng-template> element labeled #elseBlock.

ngIf with then and else to show alternate templates

You can also have both then and else block with ngIf. Then part is executed if the condition is true, else block is executed otherwise.

<div *ngIf="show; then thenBlock else elseBlock"></div>
<ng-template #thenBlock><p>This text is displayed when condition is true.</p></ng-template>
<ng-template #elseBlock><p>This text is displayed when condition is false.</p></ng-template>

Here both then and else template bindings are used which point to <ng-template> elements labeled #thenBlock and #elseBlock. The above statement is expanded into the following form by Angular. As you may notice you can also separate multiple conditions using ng-template yourself to make code more readable.

<ng-template [ngIf]="show" [ngIfThen]="thenBlock" [ngIfElse]="elseBlock">
  <div></div>
</ng-template>
   
<ng-template #thenBlock2>
  <p>This text is displayed when condition is true.</p>
</ng-template>
   
<ng-template #elseBlock>
  <p>This text is displayed when condition is false.</p>
</ng-template>

ng-template with ngTemplateOutlet to display content

Using ng-template you can define a template and NgTemplateOutlet directive inserts an embedded view from a prepared TemplateRef. So using both of them you can display the content.

Let's say we have <ng-template> defined with a template reference variable (#nm) as given here-

<ng-template #nm let-name="name"><span>Hello {{name}}!</span></ng-template>

We can render this defined template using ngTemplateOutlet.

<ng-template #nm let-name="name"><span>Hello {{name}}!</span></ng-template>

<ng-container *ngTemplateOutlet="nm; context: myContext"></ng-container>

You can also pass data to ngTemplateOutlet using the ngTemplateOutletContext object. That’s how the value for {{name}} is passed.

In the typescript code context can is defined as given below.

myContext = {name: 'Angular'};

ng-template with TemplateRef and ViewContainerRef

Since ng-template defines a template that means it is an instance of type TemplateRef. Using @ViewChild decorator in Angular you can access this template instance in the Component class. Then using ViewContainerRef you can create an embedded view using this template.

app.component.html

<ng-template #nm ><span>Hello World from Angular!</span></ng-template>

app.component.ts

import { AfterViewInit, Component, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit{
  @ViewChild('nm') nameTemplate: TemplateRef<any>;
  constructor(private containerRef: ViewContainerRef){}
  ngAfterViewInit(): void {
    this.containerRef.createEmbeddedView(this.nameTemplate);
  }
}

That's all for this topic ng-template in Angular. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. How to Use ngFor and ngIf on Same Element in Angular
  2. NgNonBindable Directive in Angular
  3. How to Create a Custom Attribute Directive in Angular
  4. How to Create a Custom Structural Directive in Angular
  5. Angular @HostListener Decorator With Examples

You may also like-

  1. Setting Wild Card Route in Angular
  2. Nested Route (Child Route) in Angular
  3. Using Angular Pipes in Component or Service Classes
  4. Custom Async Validator in Angular Reactive Form
  5. HashSet in Java With Examples
  6. BigDecimal in Java With Examples
  7. Convert String to float in Python
  8. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example

No comments:

Post a Comment