Angular: template inside template
Tags: angular
Published: 2021-05-11 10:18:09

You can use a template inside a template to allow a parent component to replace a wrapper around important content.

#####TL;DR
[See this stackblitz.](https://stackblitz.com/edit/angular-template-inside-template?file=src%2Fapp%2Fapp.component.html)

### Why a template inside a template?

In my case, I have a highly reusable component with two important parts, which are tightly coupled. The issue arose when a wrapper around the second part needed to be replaced.

![Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfl93kcy77n63rk9896c.png "Without custom wrapper")

Here I want to be able to _optionally_ replace the wrapper for part B, while being able to keep part B, like this.

![Example with custom wrapper](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv5l73es979mkmee4pp3.png "With custom wrapper")
 
### Providing a template

For optionally replacing parts of a component, providing a template using a directive and reading it using `@ContentChild` is standard procedure.

The directive:
```ts
...

@Directive({
  selector: '[appWrapper]'
})
export class WrapperDirective {
  constructor(public template: TemplateRef<any>) {}
}
```

Providing the template using the directive:
```html
<subcomponent>
  <ng-template appWrapper ...>
    ...
  </ng-template>
</subcomponent>
```

Reading the directive with the template inside the component:
```ts
...

export class SubComponent {
  @ContentChild(WrapperDirective, { static: true }) wrapper?: WrapperDirective;
}
```

And finally rendering the template, using a fallback whenever none is provided:
```html
<ng-container
  *ngTemplateOutlet="wrapper?.template || defaultWrapperTemplate">
</ng-container>

<ng-template #defaultWrapperTemplate>
  ...
</ng-template>
```

Sweet, step 1 is done. 🚀 Time for the interesting part. 🙂

### Providing the template inside the template

A template can be given _context_. This is an object for passing parameters to your template, which allows it to be more dynamic. For example, a component that shows a list of items could be provided a template to render each item, where the context object is the item's data.

```html
<list>
  <ng-template listItem let-item="item">
  <div class="{{item.class}}">
    {{ item.name }}
  </div>
  </ng-template>
</list
```

The cool thing is that a variable within that context object can also be a template. 👍

By passing the part B template to the wrapper template, the wrapper template can show it inside itself where it wants.

Providing the part B template to the wrapper template:
```html
<ng-container
  *ngTemplateOutlet="wrapper?.template || defaultWrapperTemplate; context: { partBTemplate: partBTemplate }">
</ng-container>

<ng-template #partBTemplate>
  ...
</ng-template>
```

And showing the part B template inside the wrapper template:
```html
  <ng-template appWrapper let-partBTemplate="partBTemplate">
    ...

    <ng-container *ngTemplateOutlet="partBTemplate"></ng-container>
  </ng-template>
```

This is all you need! 🎉

By using the template inside a template, you can easily replace a wrapper. It is very powerful and can be provided more context information to make richer wrapping templates based on information inside the component.

To see the full thing in action, see this stackblitz:

{% stackblitz angular-template-inside-template %}

Thanks for reading!