What is ng-template, and when to use it?

Alain Chautard
Angular Training
Published in
3 min readJul 18, 2023

--

As an Angular developer, you might have encountered ng-template when using the *ngIf syntax with an else block:

<div *ngIf="condition; else elseBlock">
Content to render when the condition is true.
</div>

<ng-template #elseBlock>
Content to render when the condition is false.
</ng-template>

The thing is, under the hood, Angular is using ng-template a lot. For instance, every time we use *ngIf or *ngFor, the syntax we’re used to is syntactic sugar for ng-template.

So, when we write the following:

<div *ngIf="condition">
Content to render when the condition is true.
</div>

Angular is translating that syntax into:

<ng-template [ngIf]="condition">
<div>
Content to render when the condition is true.
</div>
</ng-template>

The shorthand syntax we use every day was created mostly for *ngFor because its ng-template form is hard to reason about:

// *ngFor shorthand form
<li *ngFor="let user of users; index as i; first as isFirst">
...
</li>

// *ngFor with ng-template - not easy to read
<ng-template ngFor let-user [ngForOf]="users"
let-i="index" let-isFirst="first">
<li>...</li>
</ng-template>
Angular Certification Exam

What’s the point of ng-template?

We just saw that Angular gives us a shorthand syntax for directives, so we don’t have to work with ng-template directly.

Why would we use ng-template then? The main properties of ng-template are:

  • Invisible in the DOM by default — the template has to be “activated” by some code.
  • Can render any sibling elements without creating additional “wrapper” parent elements.

Here’s an example where ng-template can help. I want to display these two sibling elements when a user is logged in:

<div>
Welcome to our app, {{userName}}!
</div>
<menu>
Here are your options for today:
...
</menu>

We could use multiple *ngIf directives, but that’s not super clean — it’s easy to forget one of them if the code gets updated in the future:

<div *ngIf="user.isLoggedIn">
Welcome to our app, {{userName}}!
</div>
<menu *ngIf="user.isLoggedIn">
Here are your options for today:
...
</menu>

We could alter our HTML structure and add a wrapper element so there’s only one *ngIf, but this can impact our application layout and involve CSS changes, which isn’t ideal either:

<div *ngIf="user.isLoggedIn">
<div>
Welcome to our app, {{userName}}!
</div>
<menu>
Here are your options for today:
...
</menu>
</div>

Or we can use ng-template and have a unique, non-intrusive ngIf directive to render our HTML:

<ng-template [ngIf]="user.isLoggedIn">
<div>
Welcome to our app, {{userName}}!
</div>
<menu>
Here are your options for today:
...
</menu>
</ng-template>

This last example is the best solution as it has no downside. This is an example where ng-template shines.

Using ng-template to pass a template to another component

Another important (and more advanced) use case for ng-template is to create a template in a parent component and pass it to a child component.

Here’s a code example:

<ng-template #userInfo>
<div>
Welcome to our app, {{userName}}!
</div>
<menu>
Here are your options for today:
...
</menu>
</ng-template>

<welcome-page [userTemplate]="userInfo" >
</welcome-page>

This can be used when content projection isn’t a good fit (usually, that’s when the number of templates is variable — content projection is static, not dynamic). You can learn more about this technique in my tutorial: How to pass a custom template to an Angular component?

My name is Alain Chautard. I am a Google Developer Expert in Angular and a consultant and trainer at Angular Training, where I help web development teams learn and become comfortable with Angular.

If you need any help with web development, feel free to get in touch!

If you enjoyed this article, please clap for it or share it. Your help is always appreciated. You can also subscribe to my articles and my Daily Angular Newsletter to receive helpful daily tips.

--

--