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>
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.
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.
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>
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.
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>
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
Top comments (0)