Angular ng-template, ng-container and ngTemplateOutlet usages
Tags: angular, typescript
Published: 2020-08-19 17:06:00

## **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.

  ```html
  <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>
  ```

* 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

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

In this case angular will throw below error

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

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

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

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
  ```html
  <p>
    I turned the corner
    <ng-container *ngIf="hero">
      and saw {{hero.name}}. I waved
    </ng-container>
    and continued on my way.
  </p>
  ```
  and the output will look like
  ![Sample](https://angular.io/generated/images/guide/structural-directives/good-paragraph.png)
- 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.
1. **ngTemplateOutlet**: This of type **TemplateRef\<any\>** which will be the reference of the **ng-template**.

   Let's look at the simple example below

```typescript
@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' };
}
```

Let's breakdown the example above

1. The template ref for the ng-template **sample** is passing as first parameter
1. The second parameter Context is assigned with variable **ctx** which of type **Object**.
1. 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**.