Introduction

ng-container is an element available in Angular 2+ that can act as the host to structural directives.
In this article, you will explore scenarios that can be addressed with ng-container.

Prerequisites

If you would like to follow along with this article, you will need:

Familiarity with the structure of the DOM. To learn more, check out the tutorial series Understanding the DOM.
Some familiarity with Angular templates and structural directives may also be helpful.

Using ng-container to Avoid Redundant Elements

In Angular, you cannot use more than one template binding on an element.
This example combining *ngIf and *ngFor structural directives will not compile:

Invalid Example<div *ngIf="todos" *ngFor="let todo of todos">
  {{ todo.content }}
</div>

Attempting to compile this code will result in the following error:

Invalid Example Can't have multiple template bindings on one element. Use only one attribute prefixed with *

One workaround would be to separate the template bindings and create a wrapper:

Valid Example<div *ngIf="todos">
  <div *ngFor="let todo of todos">
    {{ todo.content }}
  </div>
</div>

One downside is that this approach is it introduces a redundant div element to the DOM:

Valid Example <div>
  <div>
    Todo Content 1
  </div>
  <div>
    Todo Content 2
  </div>
  <div>
    Todo Content 3
  </div>
</div>

This is where the ng-container element becomes useful.
The following behaves exactly the same, but without adding any extra element to the DOM at runtime:

Improved Valid Example<ng-container *ngIf="todos">
  <div *ngFor="let todo of todos">
    {{ todo.content }}
  </div>
</ng-container>

This would result in the following markup:

Improved Example <div>
  Todo Content 1
</div>
<div>
  Todo Content 2
</div>
<div>
  Todo Content 3
</div>

ng-container is also useful in situations where ngIf is used on inline content:

Example<div>
  <span *ngIf="error">Oops:</span> {{ message }}
</div>

If error is true, this would result in the following markup:

Example <div>
  <span>Oops:</span> An error occurred.
</div>

Replacing the span element with an ng-container will reduce redundant span elements added to the DOM:

Improved Example<div>
  <ng-container *ngIf="error">Oops:</ng-container> {{ message }}
</div>

If error is true, this would result in the following markup:

Improved Example <div>
  Oops: An error occurred.
</div>

Reducing the amount of markup in your application ultimately results in a smaller DOM tree and can help avoid side effects with Cascading Style Sheet selectors.

Using ng-container to Ensure Valid HTML Standards

ng-container can also resolve the problem of invalid HTML markup in situations where using a div or span would not be valid HTML.
The following example would produce invalid HTML because li elements are expected to the be the direct children of the ul element:

Invalid Example<ul>
  <div *ngFor="let todo of todos">
    <li *ngIf="todo.content !== 'Done'">
      {{ todo.content }}
    </li>
  </div>
</ul>

Replacing the div with an ng-container resolves this issue:

Valid Example<ul>
  <ng-container *ngFor="let todo of todos">
    <li *ngIf="todo.content !== 'Done'">
      {{ todo.content }}
    </li>
  </ng-container>
</ul>

Having valid HTML will satisfy stricter tests and requirements and ensure support across browsers and devices.

Conclusion

In this article, you explored the problems that ng-container addresses in your Angular applications, like redundant elements and invalid HTML standards.
If you’d like to learn more about Angular, check out our Angular topic page for exercises and programming projects.