When I first explored template handling and dynamic content in Angular, I was struck by how many directives—ng-template, ng-container, and ng-content—seemed to overlap. They look quite alike at first glance, yet each carries its own distinct set of features and practical scenarios.

Below, I’ll walk through different situations where ng-template, ng-container, and ng-content shine, using concrete examples to highlight when each directive is the right choice. To start, here’s a quick breakdown of each:

  • ng-template lets you declare a template block that you can reuse as many times as needed inside an Angular component.

  • ng-container is meant for grouping elements without introducing extra nodes into the resulting DOM.

  • ng-content handles the rendering of content supplied by a parent component.

ng-template

ng-template defines a template block that can serve as the basis for rendering content on demand. It gives you a way to write HTML that you can reutilize across multiple locations within a single component.

A typical scenario is using ng-template alongside ngIf or ngSwitch to display conditional content.

<ng-template #myTemplate>
  <div *ngIf="hasBalance">
    <p>Your amount is 5000€.</p>
  </div>
  <div *ngIf="!hasBalance">
    <p>Sorry, no balance.</p>
  </div>
</ng-template>
Enter fullscreen mode Exit fullscreen mode

Here, the template block holds two div elements, each governed by an *ngIf directive. Depending on the value of hasBalance, one of these div elements will be shown.

That same template block can be referenced in several places inside the component via an ng-container element:

<ng-container *ngTemplateOutlet="myTemplate"></ng-container>
Enter fullscreen mode Exit fullscreen mode

ng-container

ng-container enables grouping of elements without inserting any extra nodes into the DOM. It pairs well with structural directives such as *ngIf, *ngFor, and *ngSwitch.

A frequent use case is applying a structural directive to multiple elements at once, without needing a wrapper HTML element. Consider this:

  <div *ngIf="hasBalance">
    <p>Your amount is 5000€.</p>
  </div>
  <div *ngIf="!hasBalance">
    <p>Sorry, no balance.</p>
  </div>
Enter fullscreen mode Exit fullscreen mode

In that snippet, the two div elements each use *ngIf separately. However, if the same *ngIf condition were meant to control both, an extra wrapper tag would normally be required:

<div *ngIf="activeSession">
  <div *ngIf="hasBalance">
    <p>Your amount is 5000.</p>
  </div>
  <div *ngIf="!hasBalance">
    <p>Sorry, no balance.</p>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

That additional div adds no real value. An ng-container can serve the same purpose—grouping those div elements—without producing any tag in the output:

<ng-container *ngIf="activeSession">
  <div *ngIf="hasBalance">
    <p>Your amount is 5000.</p>
  </div>
  <div *ngIf="!hasBalance">
    <p>Sorry, no balance.</p>
  </div>
</ng-container>
Enter fullscreen mode Exit fullscreen mode

Here, the ng-container bundles the div elements together with no extra HTML node in the DOM.

ng-content

ng-content offers a straightforward mechanism for rendering content that arrives from a parent component. It lets a parent component inject arbitrary markup into a child component’s view.

A classic example is building a reusable component designed to display different content depending on the context. For instance:

@Component({
  selector: 'app-alert',
  template: `
    <div class="alert alert-{{type}}">
      <ng-content></ng-content>
    </div>
  `
})
export class AlertComponent {
  @Input() type: string;
}
Enter fullscreen mode Exit fullscreen mode

Here, an AlertComponent receives a type input and relies on ng-content to project whatever content the parent passes in. The parent component can then use it like this:

<app-alert type="success">
  <p>Success!</p>
</app-alert>

<app-alert type="danger">
  <p>Something went wrong!</p>
</app-alert>
Enter fullscreen mode Exit fullscreen mode

In this setup, AlertComponent is used to show both success and error messages. Whatever is placed inside the component tag gets rendered at the ng-content location in the template.

Conclusion

All three—ng-template, ng-container, and ng-content—are frequently used directives in Angular templates. They might seem interchangeable on the surface, but they each fulfill a specific role.

The examples and scenarios above should give you a clearer sense of when and how to apply each directive effectively.

Photo by Kelly Sikkema on Unsplash