Angular: Content Projection end to end
Tags: javascript, typescript, angular, webdev
Published: 2022-08-12 06:41:00

Content projection is a pattern in which you insert the content that you want to show inside another component. 

`<ng-content></ng-content>` - responsible to project content inside another component. It is just a placeholder and will be replaced by actual projected content.

There are several ways of doing this in Angular:

1. <u>Single-slot content projection:</u> other component accepts content from single source

```html
<!--app.component.html-->
<app-child>
<p>project this content</p>
</app-child>

<!--child.component.html-->
<p>Single-slot content projection</p>
<ng-content></ng-content>
```
output:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8c4unzkg5xhvfa957v4o.png)

2. <u>Multi-slot content projection:</u> Component accepts content from multiple sources. Hence, we must specify where to project content. We can accomplish this task by `select` attribute of `<ng-content>`

```html
<!--app.component.html-->
<app-child>
<p> First project content </p>
<p select="[foo]"> foo project content </p>
<p select="[bar]"> bar project content </p>
<p> Lastly projected content </p>
</app-child>

<!--child.component.html-->
<h2>Multi-slot content projection</h2>
<ng-content></ng-content>
<ng-content #foo></ng-content>
<ng-content #bar></ng-content>

```
output:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mcg79vn0u3q5rk4r44td.png)

Note: An <ng-content> element without a select attribute receives all projected components that do not match any of the other <ng-content> elements.

 - If you observe above the `Lastly projected content` doesn't have any `select` but still projected via empty `ng-content`.


3. <u>Conditional Content Projection:</u> Achieved using `<ng-template>` and `ngTemplateOutlet` directive. 

```html
<h2>Conditional Content Projection</h2>

<p>Basic Template outlet Implementation</p>

<ng-template #template1>
  <p>template info</p>
</ng-template>

<p>It prints before templateInfo</p>

<ng-container *ngTemplateOutlet="template1"> </ng-container>
```
`ngTemplateOutlet` is a structural directive used to insert `ng-template` in various sections of DOM.

User can use any element like div. But div won't be rendered

```html
 <div *ngTemplateOutlet="template1"></div>
```

Output:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xe4on6sflclr5xxhcc3h.png)

We can also pass value to `ngTemplateOutlet` using `ngTemplateOutletContext` property.

```html
<p>Passing value to template outlet</p>

<ng-template let-value="value" #template2>
  <p>Value recieved: {{ value }}</p>
</ng-template>

<ng-container
  [ngTemplateOutlet]="template2"
  [ngTemplateOutletContext]="{ value: 100 }"
>
</ng-container>

<!--Alternatively-->
<ng-container
  *ngTemplateOutlet="template2; context: { value: 100 }"
></ng-container>
```

We can also send multiple values. 

Output:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dtclo6virdaqxy6kmv9y.png)

You can view the complete output here:

{% embed https://angular-ivy-ym33ea.stackblitz.io %}

Please let me know if I miss to cover any cases. 

You can follow me: https://twitter.com/urstrulyvishwak

Thanks