How To Use ngTemplateOutlet In Angular
In this article, we will learn how to use ngTemplateOutlet Angular. A directive is ngTemplateOutlet. It uses a template reference and a context object as arguments to dynamically create a template. We'll show you a few ngTemplateOutlet examples to get you started.
What is ngTemplateOutlet?
The structural directive ngTemplateOutlet is used to create a template. It's used to insert a template (generated by ngTemplate) into various DOM areas. For example, you can define a few templates to display an item and use them to display it in multiple locations across the View, as well as change the template based on the user's preference.
How to use ngTemplateOutlet
Let's start with a very basic ngTemplateOutlet example.
The ng-template is used to define a template in the following code. The Template reference variable stores the template's reference. (TemplateRef).
The template is not self-rendering. To render it, we'll need to employ a structural directive. ngTemplateOutlet accomplishes this.
The Template Reference directive is passed to the ngTemplateOutlet directive. The template is rendered. Any inside content encapsulated by ngTemplateOutlet will not be rendered.
<h3>Example 1</h3> <!-- This is our template. template1 is the template reference variable holds the reference to the Template template1 is of type TemplateRef This won't be rendered here --> <ng-template #template1> <p>This is our template. It will be displayed on the div *ngTemplateOutlet="myTemplateRef"</p> </ng-template> <p>The Template appears after this</p> <!-- We want to render the above template here. Hence we use the ngTemplateOutlet directive Assign template1 to ngTemplateOutlet --> <ng-container *ngTemplateOutlet="template1"> This text is not displayed </ng-container> <!-- Use can use any element. Here we use div instead of ng-container Div is not rendered --> <div *ngTemplateOutlet="template1"> </div>
The div in the following code is not rendered.
<div *ngTemplateOutlet="template1"> </div>
i.e., because the angular transforms the preceding into the ng-template syntax. The ngTemplateOutlet renders the template pointed by template1 by replacing everything inside the ng-template element.
<ng-template [ngTemplateOutlet]="template1"> <div></div> </ng-template>
Passing data to ngTemplateOutlet
<ng-template let-value="value" #messageTemplate> <p>Value Received from the Parent is {{value}}</p> </ng-template>
Using the ngTemplateOutletContextproperty, we can provide any value to the value.
<ng-container [ngTemplateOutlet]="messageTemplate" [ngTemplateOutletContext] ="{value:'1000'}"> </ng-container>
You can also use the following syntax as an alternative.
<ng-container *ngTemplateOutlet="messageTemplate; context:{value:100}"> </ng-container>
Pass more than one value.
<ng-template let-name="nameVar" let-message="messageVar" #template3> <p>Dear {{name}} , {{message}} </p> </ng-template>
<ng-container [ngTemplateOutlet]="templates" [ngTemplateOutletContext] ="{nameVar:'Guest',messageVar:'Welcome to our site'}"> </ng-container>
Pass an object.
<ng-template let-person="person" #template4> <p>Dear {{person.name}} , {{person.message}} </p> </ng-template>
<ng-container [ngTemplateOutlet]="templates" [ngTemplateOutletContext] ="{ person:{name:'Guest',message:'Welcome to our site'} }"> </ng-container>
Using $implicit
<ng-template let-name let-message="message" #template3> <p>Dear {{name}} , {{message}} </p> </ng-template> <ng-container [ngTemplateOutlet]="templates" [ngTemplateOutletContext] ="{$implicit:'Guest',message:'Welcome to our site'}"> </ng-container>
In the following code, the value for both name and message is obtained from the $implicit, i.e. Guest.
<ng-template let-name let-message #template3> <p>Dear {{name}} , {{message}} </p> </ng-template> <ng-container [ngTemplateOutlet]="template3" [ngTemplateOutletContext] ="{$implicit:'Guest',message:'Welcome to our site'}"> </ng-container>
Passing Template to a Child Component
import { Component, TemplateRef, Input } from '@angular/core'; @Component({ selector: 'parent', template: ` <h1>Parent component</h1> <ng-template #parentTemplate> <p> This Template is defined in Parent. We will send it to child component </p> </ng-template> <child [customTemplate]="parentTemplate"></child> ` }) export class ParentComponent { }
Components in the Child receive the parentTemplate via @Input(). After that, you should provide it to ngTemplateOutlet.
@Component({ selector: 'child', template: ` <h2>Child component</h2> <ng-container *ngTemplateOutlet="customTemplate"> </ng-container> ` }) export class ChildComponent { @Input() customTemplate: TemplateRef<HTMLElement>; }
Using ViewChild to Access the template
import { Component, TemplateRef, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core'; @Component({ selector: 'parent', template: ` <h1>Parent component</h1> <ng-template #parentTemplate> <p> This Template is defined in Parent. We will send it to child component </p> </ng-template> <child [customTemplate]="parentTemplate"></child> ` }) export class ParentComponent implements OnInit, AfterViewInit { @ViewChild('parentTemplate',null) myTemplate:TemplateRef<HTMLElement>; ngAfterViewInit() { console.log(this.myTemplate) } }
Content Projection and ngTemplate
import { Component, TemplateRef, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core'; @Component({ selector: 'parent1', template: ` <h1>Parent Component </h1> <child1> <p>This Template is Projected to the Child</p> </child1> ` }) export class Parent1Component { }
We put it in a ngTemplate in the child.
import { Component, TemplateRef, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core'; @Component({ selector: 'child1', template: ` <h1>Child Component </h1> <ng-template #parentTemplate> <ng-content></ng-content> </ng-template> <ng-template [ngTemplateOutlet]="parentTemplate"></ng-template> ` }) export class Child1Component { }
ngTemplateOutlet Example
<label for="mode">Display Mode:</label> <select [(ngModel)]="mode"> <option *ngFor="let item of modeOptions" [ngValue]="item.mode">{{item.mode}}</option> </select>
Make a template for the card display next. CardTemplate is the name you should give it. Items are input into the template. To show the item header and content in a card format, loop through the items collection using the ngFor.
<ng-template let-items #cardTemplate> <div *ngFor="let item of items"> <h1>{{item.header}}</h1> <p>{{item.content}}</p> </div> </ng-template>
The ul is used by the listTemplate to display the elements in a list manner.
<ng-template let-items #listTemplate> <ul> <li *ngFor="let item of items"> <strong>{{item.header}} </strong> ( {{item.content}} ) </li> </ul> </ng-template>
Finally, the items are passed to the item-view component. We also provide it the template.
<item-view [itemTemplate]="template" [items]="items"> </item-view>
@ViewChild('cardTemplate',null) cardTemplate:TemplateRef<HTMLElement>; @ViewChild('listTemplate',null) listTemplate:TemplateRef<HTMLElement>;
Define the items, mode, and modeOptions variables.
mode ="card" items = [ { header: 'Angular article', content: 'The Angular article for Beginners & Professionals' }, { header: 'Typescript article', content: 'The Complete Guide to Typescript' }, { header: 'Entity Framework Code article', content: 'Learn Everything about Entity Framework Core' }, ]; modeOptions = [ { mode: "card" }, { mode: "list" }, ];
Depending on the option of mode, the template returns either a listTemplate or a cardTemplate.
get template() { if(this.mode=="list") return this.listTemplate return this.cardTemplate }
From the parent component, the ItemViewComponent receives the items to display and the itemTemplate to use.
@Input() items: any[] = []; @Input() itemTemplate: TemplateRef<HTMLElement>;
Please pass the item on. To display the item, send a template to the ngTemplateOutlet. To pass the items collection, use the ngTemplateOutletContext.
<ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{$implicit:items}"> </ng-container>
import { Component, TemplateRef, ViewChild } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'ngTemplateOutlet Example'; @ViewChild('cardTemplate',null) cardTemplate:TemplateRef<HTMLElement>; @ViewChild('listTemplate',null) listTemplate:TemplateRef<HTMLElement>; mode ="card" items = [ { header: 'Angular article', content: 'The Angular article for Beginners & Professionals' }, { header: 'Typescript article', content: 'The Complete Guide to Typescript' }, { header: 'Entity Framework Code article', content: 'Learn Everything about Entity Framework Core' }, ]; modeOptions = [ { mode: "card" }, { mode: "list" }, ]; get template() { if(this.mode=="list") return this.listTemplate return this.cardTemplate } }
The code of the app.component.html file:
<h1>ngTemplateOutlet Example</h1> <label for="mode">Display Mode:</label> <select [(ngModel)]="mode"> <option *ngFor="let item of modeOptions" [ngValue]="item.mode">{{item.mode}}</option> </select> <ng-template let-items #cardTemplate> <div *ngFor="let item of items"> <h1>{{item.header}}</h1> <p>{{item.content}}</p> </div> </ng-template> <ng-template let-items #listTemplate> <ul> <li *ngFor="let item of items"> <strong>{{item.header}} </strong> ( {{item.content}} ) </li> </ul> </ng-template> <item-view [itemTemplate]="template" [items]="items"> </item-view>
The code of the item-view.component.ts:
import { Component, Input, TemplateRef } from '@angular/core'; @Component({ selector: 'item-view', template: ` <h2>Item View</h2> <ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{$implicit:items}"> </ng-container> ` }) export class ItemViewComponent { @Input() items: any[] = []; @Input() itemTemplate: TemplateRef<HTMLElement>; }
The code of the app.module.ts:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule} from '@angular/forms'; import { AppComponent } from './app.component'; import { ItemViewComponent } from './item-view.component'; @NgModule({ declarations: [ AppComponent, ItemViewComponent ], imports: [ BrowserModule,FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }