DEV Community

loading...
Cover image for Ng-magical directives series (ng-template)

Ng-magical directives series (ng-template)

Valentine Awe
I am a Senior Software Engineer with a demonstrated history of working in the financial services industry designing and architecting scalable software applications
Updated on ・3 min read

Magic is just science that we do not understand yet
...Arthur C. Clarke

This article is part of what I call the magical directives series. In this series, we will unravel the mystery behind some interesting Angular directives. Afterwards, we can add this little magic to our tool box. I call them magical directives because they play a very important role in building reusable components across our Angular applications.

Below are the directives that we will be looking at in this series.

  • ng-template
  • ng-container
  • ng-content
  • *ngTemplateOutlet

The ng-template

The ng-template directive simply represent an Angular template. Angular uses the ng-template under the hood in our structural directives( *ngIf, *ngFor) and ngSwitch. The ngSwitch controls the structural directives (*ngSwitchCase and *ngSwitchDefault ) and it is an attribute directive.

Whenever we use any of these structural directives, Angular does the below.

<!-- Your actual code with a structural directive -->

<div *ngIf="food">
  <p>some interesting contents</p>
<div>

<!-- What Angular does behind the scene-->

<ng-template [ngIf]="food">
  <div>
    <p>some interesting contents</p>
  </div>
</ng-template>

Enter fullscreen mode Exit fullscreen mode

From the above code sample, Angular sees the asterisk (*) in the *ngIf and automatically recognizes it as a structural directive. It then wraps the host element inside an ng-template, this is the same for other structural directives. What makes it more beautiful is that, Angular comments the ng-template directive (as seen in green text in the image below), so the ng-template is never displayed as a tag in the DOM tree.

image

NB: Angular does not display the content of the ng-template by default. The ng-template only represents a template which you can then decide how you want it to be displayed.

image

From the image above, Angular converts the * into an ng-template which then result to a nested ng-template. Since Angular does not display the content of the ng-template, We will end up with just comments

If you decide to write your structural directives inside the ng-template, you will just have to replicate what Angular does when it sees a structural directive. E.g for *ngIf, it will be <ng-template [*ngIf]=""> </ng-template> As seen in the first code sample above. You can do the same for other structural directives and it will work just fine. Below is an example with ngSwitch.

<!-- ngSwtich with structural directives *ngSwitchCase and *ngSwitchDefault -->

<div [ngSwitch]="food">
    <div *ngSwitchCase="'Beans'"> yeah... Sweet Beans</div>
    <div *ngSwitchCase="'Rice'"> ummm.. Yummy rice</div>
    <div *ngSwitchDefault>No Food Selected</div>
</div>

<!-- ngSwitch with ng-template  -->

<div [ngSwitch]="food">
    <ng-template [ngSwitchCase]="'Beans'"> yeah... Sweet Beans</ng-template>
    <ng-template [ngSwitchCase]="'Rice'"> ummm.. Yummy rice</ng-template>
    <ng-template ngSwitchDefault>No Food Selected</ng-template>
</div>

Enter fullscreen mode Exit fullscreen mode

Using the ng-template can help remove redundant elements from your DOM tree when necessary. As seen in the code sample with the ngSwtich and ng-template, there won't be an extra div created in the DOM tree compare to the first sample without the ng-template. Although, it could sometimes be easier and cleaner in most cases to use the * i.e instead of wrapping the host inside the ng-template.

But wait, there are other interesting ways that you can utilize the magical effect of the ng-template and one of them is with the ngIf-else and ngIf-else-then

Let us take for instance that you are working on an application where you want to display a certain template based on a condition. In this case, you can enclose the templates in an ng-template and add a reference to each template so that whenever a certain condition is met, the corresponding template will be displayed as seen in the image below.

image

A common use case is when you are waiting for a response from the server and you want to temporary display a loader until you receive the response.

<!-- use case for If else -->
<div *ngIf="result else loading">
   <p>{{result}}</p>
</div>


<!-- our loader template -->

<ng-template #loading>
    Loading ...
</ng-template>

Enter fullscreen mode Exit fullscreen mode

Here, the default display will be 'Loading..' until we get the result from the server.

Summary

The magical effects of the ng-template cannot be over emphasized. In the rest of the series, we will see how to use the ng-template along with the other directives.

Next: ng-container

Discussion (0)