Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • ng-template, ng-container & ngTemplateOutlet - Angular Templates Guide with Example

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 1
    • 0
    • 3.55k
    Comment on it

    In this blog we will discuss about advanced features of angular core.

     

     

    ng-container, ng-template and ngTemplateOutlet are angular core directives which on combining together allows the creation of highly dynamical and customizable angular components. Based on these templates, a look of a component can be changed completely like whenever a template is defined it can be instantiated in various places.

     

    1. <ng-template>

     

    <ng-template> is defined as an angular element which is used for rendering HTML. This element is never displayed directly means code inside <ng-template> is not displayed but represented as a comment initially. Let's is with the following example:-

     

    app.component.ts - Parent Component i.e  "AppComponent" is defined in this file.

    import { Component } from '@angular/core';
    
    @Component({
     selector: 'app-root',
     templateUrl: './app.component.html',
    })
    export class AppComponent {
    }

     

    app.component.html -This file contains component view

    <ng-template>
     <p>Demo Example</p>
    </ng-template>

     

    Root module  -  app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    
    
    @NgModule({
     declarations: [
      AppComponent
     ],
     imports: [
      BrowserModule
     ],
     providers: [],
     bootstrap: [AppComponent]
    })
    export class AppModule { }

     

    When above code runs, <ng-template> will be represented as a comment "<!---->"

     

    Output :-


    In above output, it can be seen that place of <ng-template> is occupied by comments.

    Structural directive, ViewContainerRef, TemplateRef etc are used for displaying <ng-template> element.

     

    Using ng-template with structural directive.

    Below we will discuss usage of ng-template with the structural directive like ngFor which is used for repeating a given HTML template once for each value in an array, ngIf used for showing or hiding an element based on condition.

     

    <ng-template> with structural directive ngFor

    Following changes are made in above files in order to use <ng-template> with ngFor.

     

    app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
     selector: 'app-root',
     templateUrl: './app.component.html',
    })
    export class AppComponent {
     students = [
      { name:"Yogesh",stream:"science" },
      { name:"Mithlesh",stream:"commerce" },
      { name:"Anu",stream:"Humanities" },
      { name:"Aditi",stream:"commerce" },
     ]
    }

    In above component a simple students array is declared, which will be displayed in component template through ngFor.

     

    app.component.html

    <h3>ng-template with directive ngFor</h3>
    <ng-template ngFor let-student [ngForOf]= "students" let-i="index">
     <p>{{i + 1}}. {{student.name}} : {{student.stream}} </p>
    </ng-template>

     

    In above component view, template input variable is declared via let. The properties such as index, first, last, even, odd related to NgFor can be assigned to a variable using let within the <ng-template>.

    Root module i.e app.module.ts file remain same.

    When above code runs, code within ng-template will be displayed as it is used with the structural directive "ngFor".

     

    Output :-

     

    <ng-template> with conditional structural directive ngIf

     

    Following changes are made to component view i.e app.component.html file

    <h3>ng-template with directive ngIf</h3>
    <ul *ngFor="let student of students; let i = index">
     <ng-template [ngIf]= "student.stream == 'commerce'" ><li>{{student.name}} : {{student.stream}}</li></ng-template>
    </ul>

    In above code, <ng-template> code is only displayed if certain condition is satisfied i.e only student with stream "commerce" will be displayed.

    Remaining files remain same . 

     

    Output :-

     

     

    Using <ng-template> with TemplateRef and ViewContainerRef

    This is entirely a new example, in this we are showing that code(which is a simple message) within ng-template can be displayed multiple times using TemplateRef and ViewContainerRef.

    Create a directive "MessageDirective" in a file "message.directive.ts"

    import { Directive, ViewContainerRef } from '@angular/core';
    
    @Directive({
     selector: '[commonMessage]'
    })
    export class MessageDirective {
    
     constructor(public viewContainerRef:ViewContainerRef) { }
    
    }

    It is a simple directive which is used as an attribute selector of an element having ViewContainerRef as dependency injection.

     

    app.component.html

    <h3>ng-template example with TemplateRef and ViewContainerRef</h3>
    
    <ng-template #commonmsg>
     Welcome to Angular learning.<br/>
    </ng-template>
    
    <h3>Message </h3>
    
    <div commonMsg> </div>
    
    <h3>Message </h3>
    
    <div commonMsg> </div>

     

    Template reference variable "commonmsg" is assigned to ng-template. MessageDirective is being used with attribute selector directive  "commonMsg" in various div element.


    app.component.ts

    import { Component,ViewChild,ViewChildren,TemplateRef,QueryList,AfterViewInit } from '@angular/core';
    import { MessageDirective } from './message.directive';
    
    @Component({
     selector: 'app-root',
     templateUrl: './app.component.html',
    })
    export class AppComponent implements AfterViewInit {
      @ViewChild('commonmsg') private commonMsgTempRef : TemplateRef<any>
     
      @ViewChildren(MessageDirective) private messageDirectiveQueryList: QueryList<MessageDirective>
     
      ngAfterViewInit() {
        this.messageDirectiveQueryList.map(messageDirective =>
        messageDirective.viewContainerRef.createEmbeddedView(this.commonMsgTempRef)); 
      }
    }

    In above code <ng-template> reference is accessed as TemplateRef via ViewChild. Here a view container reference is provided by directive. Therefore all view container references provided by directive will be fetched using @ViewChildren() and QueryList. Finally template reference is embedded to all view container references. In short data obtained via template reference variable is embedded to elements wherever message directive is used.

     

    Output :-

     

    2. <ng-container>

     

    ng-container find it's usage when multiple structural directives are to be used together. Let's consider an example where we are using multiple structural directives :-

     

    app.component.html

    <ul *ngFor="let student of students; let i = index" *ngIf= "students">
     <li>{{student.name}} : {{student.stream}}</li>
    </ul>

     

    app.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
    })
    export class AppComponent {
      students = [
        { name:"Yogesh",stream:"science" },
        { name:"Mithlesh",stream:"commerce" },
        { name:"Anu",stream:"Humanities" },
        { name:"Aditi",stream:"commerce" },
      ]
    }


    Above code will not work and give following error :-

     

     

    This shows that two structural directives cannot be used together to the same element. To make above code work following changes is to be made :-

     

    app.component.html

    <div *ngIf= "students">
     <ul *ngFor="let student of students; let i = index">
      <li>{{student.name}} : {{student.stream}}</li>
    </ul>
    </div>

     

    ngIf directive is moved to outer div element thereby creating an extra div element. To avoid such scenario angular provided <ng-container> to apply multiple structural directive without creating an extra div element.

     

    app.component.html

    <ng-container *ngIf= "students">
     <ul *ngFor="let student of students; let i = index">
      <li>{{student.name}} : {{student.stream}}</li>
    </ul>
    </ng-container>

     

     

    3. ngTemplateOutlet

     

    An embedded view from a prepared TemplateRef can be inserted via ngTemplateOutlet. Let's see an example:

     

    app.component.html

    <ng-template #studentlist>
     <ul *ngFor="let student of students; let i = index">
      <li>{{student.name}} : {{student.stream}}</li>
     </ul>
    </ng-template>
    
    <ng-container *ngTemplateOutlet="studentlist"></ng-container>

     

    The template being loaded is refered via template reference "#studentlist" and ngTemplateOutlet is used to instantiate the template.
     

    ng-template, ng-container & ngTemplateOutlet - Angular Templates Guide with Example

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: