DEV Community

KrishnaSai Polanki
KrishnaSai Polanki

Posted on • Updated on

Angular ng-template, ng-container and ngTemplateOutlet usages

ng-template:

ng-template is basically an angular element. By the name we can say that it contains a part of the template of a component and used to display on a conditional basis.

  • For example we can think like a text to display in grid when there is no data available.
  <div fxLayout="column" fxLayoutGap="20px">
    <div *ngIf="data.length>0; else elseBlock">
      <!-- Data Grid will display -->
    </div>
  </div>
  <ng-template #elseBlock>
    <div>
      No data is available to display
    </div>
  </ng-template>
Enter fullscreen mode Exit fullscreen mode
  • This cannot be used as standalone element. Angular will comment this in the render HTML
  • There should be some structural directives.
  • Under the hood Angular directives like ngIf,ngFor and ngSwitch uses the ng-template.

Let's think of scenario where we need to use more than one structural directives like below

<div fxLayout="column" fxLayoutGap="20px">
  <div *ngIf="data.length>0" *ngFor="let d of data">
    {{d.name}}
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

In this case angular will throw below error

Uncaught Error: Template parse errors:
Can't have multiple template bindings on one element. Use only one attribute
named 'template' or prefixed with *
Enter fullscreen mode Exit fullscreen mode

To avoid that we need to add an extra HTML tag like below.

<div fxLayout="column" fxLayoutGap="20px">
  <div *ngIf="data.length>0">
    <div *ngFor="let d of data">
      {{d.name}}
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Can't we do without adding an extra HTML tag? Here comes the ng-container to rescue this problem. Let's get to know more details about it.

ng-container:

ng-container is a grouping element in angular, it doesn't interfere with any of the styles or layout as the angular doesn't put it into the DOM.

  • See below example which show the ng-container doesn't interfere with layout
  <p>
    I turned the corner
    <ng-container *ngIf="hero">
      and saw {{hero.name}}. I waved
    </ng-container>
    and continued on my way.
  </p>
Enter fullscreen mode Exit fullscreen mode

and the output will look like
Sample

  • The other most import feature of ng-container is, it acts as placeholder where we can inject the template dynamically with the help of ngTemplateOutlet.

let's discuss more about the ngTemplateOutlet before going to see the combined uses of ng-template, ng-container and ngTemplateOutlet.

ngTemplateOutlet:

ngTemplateOutlet is an Angular directive which is used to instantiate the template dynamically. We can have multiple number of ngTemplateOutlet in a component template to render the templates dynamically.

This has two properties

  1. ngTemplateOutletContext: This is of type Object which is used to pass the dynamic data into the template.The object keys will be available for the local variable can be defined using the let keyword to bind the values inside the template. Using the key $implicit in the context object will set its value as default.
  2. ngTemplateOutlet: This of type TemplateRef<any> which will be the reference of the ng-template.

Let's look at the simple example below

@Component({
  selector: 'ng-template-outlet-example',
  template: `
    <ng-container *ngTemplateOutlet="sample; context: ctx"></ng-container>
    <hr />

    <ng-template #sample let-word let-person="name"
      ><span>Hello {{ word }}! from {{ name }}</span></ng-template
    >
  `,
})
export class NgTemplateOutletExample {
  ctx = { $implicit: 'World', name: 'Krishna' };
}
Enter fullscreen mode Exit fullscreen mode

Let's breakdown the example above

  1. The template ref for the ng-template sample is passing as first parameter
  2. The second parameter Context is assigned with variable ctx which of type Object.
  3. If we notice the default key in ctx which is $implicit is assigned to local variable word and the key name is assigned to local variable person.

Top comments (1)

Collapse
 
brianreinhold profile image
brianreinhold

I guess this is only meant to use inside a single component template. I certainly cannot use it in another component template.