Angular ng-template, ng-container, ngTemplateOutlet

  • ng-template is a directive which can be invoked based on certain conditions like *ngIf, *ngFor *ngSwitch etc.,
  • We can create different templates and can be called based on the logic using *ngTemplateOutlet.
  • We can also pass properties from *ngTemplateOutlet.
  • We can also use TemplateRef and ViewContainerRef to display template

If you add the below code to your app component html page and run the code the template does not render itself on DOM and you will see blank page, because ng-template only defines a template and we need to tell angular when to display by using some conditions and where to display by using template reference variable (#variablename).

<ng-template>
  <div>Hello from template...</div>
</ng-template>

Now I am adding some rendering logic to ng-template using ngif directive to ng-template. Please check code below app.component.ts and app.component.html

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  showTemplateData = true;
  firstSection: boolean = false;

}
<ng-template [ngIf]="showTemplateData">
  <div>Hello from template...</div>
</ng-template>
<ng-template [ngIf]="firstSection" [ngIfElse]="secondSection">
  <div>
    <h1>First Section </h1>
  </div>
</ng-template>
<ng-template #secondSection>
  <div>
    <h1>Second Section</h1>
  </div>
</ng-template>
  • ng-container is a grouping element which allows us to create a section in a template without the need to create a new HTML element.
  • ng-container does not render in the DOM, but content inside it will be rended and it doesn’t interfere with styles. It is used with structural directives like ngIf, ngFor etc.
import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  showTemplateData: boolean = true;
  firstSection: boolean = false;
// Courses Object
  Courses = [
    { CourseName:'Python', Instructor: "Girish" },
    { CourseName:'Angular', Instructor: "Sanjay" },
    { CourseName:'Java', Instructor: "Santosh" },
    { CourseName:'Data Science', Instructor: "Krishna" },
    { CourseName:'PHP', Instructor: "Gopal" },
    { CourseName:'Spring Framework', Instructor: "Venkatesh" },
  ]
   }
<ng-container *ngIf="showTemplateData">
  <div *ngFor="let course of Courses">
    <p>{{course.CourseName}} : {{course.Instructor}} </p>
  </div> 
</ng-container>
<ng-container *ngIf="showTemplateData">
  <ng-template ngFor let-course [ngForOf]="Courses" let-index="index">
    {{index + 1}} {{course.CourseName}} : {{course.Instructor}} <br />
  </ng-template>
</ng-container>
  • ngTemplateOutlet directive is used to instantiate the template dynamically. We can declare multiple ngTemplateOutlet in a component template to render the templates dynamically.
  • Inside ngTemplateOutlet, the template ref for the ng-template courseTemplate is passing as first parameter
  • The second parameter Context is assigned with variable handler which of type Object. It instantiates a template dynamically using a template reference and context object as parameters.
  • If we notice the default key in handler which is $implicit is assigned to local variable company and the key total is assigned to local variable coursesCount.
  • If you use the key $implicit in the context object will set its value as default for all the local variables. For Example we have not assigned anything to the let-company, so it will take the value from the $implicit, which is ‘Tutor Girish’.
<ng-template #courseTemplate let-company let-coursesCount="total">
  <div> {{company}} Institute has {{coursesCount}} courses conducting online ...</div>
</ng-template>

<ng-container 
 *ngTemplateOutlet="courseTemplate;context:handler">
</ng-container>
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
 handler = { $implicit:'Tutor Girish', total: 25 };
}

Below let-company creates a local variable with the value name.

<ng-template #courseTemplate let-company="name" let-coursesCount="total">
  <div> {{company}} Institute has {{coursesCount}} courses conducting online ...</div>
</ng-template>

<ng-container 
 *ngTemplateOutlet="courseTemplate;context:handler">
</ng-container>
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',  
  styleUrls: ['./app.component.css']
})
export class AppComponent {
handler = { name:'Tutor Girish', total: 25 };
}
<ng-container *ngIf="showTemplateData">
  <ng-template ngFor let-course [ngForOf]="Courses" let-index="index">
    {{index + 1}} {{course.CourseName}} : {{course.Instructor}} <br />
  </ng-template>
</ng-container>

<ng-template [ngIf]="firstSection" [ngIfElse]="secondSection">
  <div>
    <h1>First Section </h1>
  </div>
</ng-template>
<ng-template #secondSection>
  <div>
    <h1>Second Section</h1>
  </div>
</ng-template>

<ng-template #courseTemplate let-company="name" let-coursesCount="total">
  <div> {{company}} Institute has {{coursesCount}} courses conducting online ...</div>
</ng-template>


<ng-container 
 *ngTemplateOutlet="courseTemplate;context:handler">
</ng-container>

Check our other Angular Tutorials at Angular Tutorials

References

  • https://angular.io/guide/template-reference-variables
  • https://angular.io/api/common/NgTemplateOutlet
  • https://angular.io/guide/structural-directives

Learn more about Angular features in the upcoming Angular Blog articles.

Happy Learning!