Content Projection in Angular using ng-content
Tags: angular, typescript, javascript
Published: 2021-08-20 10:08:42

In order to create the re-usable and flexible components content projection is a great option in Angular. Using **ng-content** we can do the content projection in Angular.

In general content projection means inserting or projecting some content from one component into another component. For example you want to insert some dynamic html element(s) into component(child component) when it is used inside a parent component.

Common implementation of content projection in Angular are

- **Single Slot Content Projection**
- **Multi Slot Content Projection**
- **Conditional Content Projection**

### Single Slot Content Projection:

Single slot content projection means there will be single source of the content which needs to project into component. Let's understand with an example.

> child-component.html (selector: _**cp-child**_)

```html
<h2>Single Slot Content Projection Example</h2>
<ng-content></ng-content>
<input type="text" />
<p>This is simple example to demonstrate the single slot content projection.</p>
```

> parent-component.html

```html
<cp-single>
  <mat-icon>email</mat-icon>
</cp-single>
<cp-single>
  <mat-icon>home</mat-icon>
</cp-single>
```

Here we can see the same component is reused by projecting different content, and the result will look like this

![Single Slot Projectiont](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uur4g4kimnplt8z4bduj.PNG)

### Multi Slot Content Projection:

Let's if there is need of projecting multiple content in to the same component then we can achieve it with multi slot projection using the **_select_** attribute of the **_ng-content_**. Let's see how it works with an example.

> child-component.html (selector: _**cp-child**_)

```html
<h2>Multi Slot Content Projection Example</h2>
<ng-content select="[projected-label]"></ng-content>
<ng-content select="[projected-icon]"></ng-content>
<input matInput />
<ng-content select="[projected-hint-msg]"></ng-content>
<p>This is simple example to demonstrate the multi slot content projection.</p>
```

> parent-component.html

```html
<cp-multi-slot>
  <mat-icon projected-icon>email</mat-icon>
  <mat-label projected-label>Enter Email</mat-label>
  <mat-hint projected-hint-msg>example@example.com</mat-hint>
</cp-multi-slot>
```

Here we can see that each **_ng-content_** has **_select_** attribute with the name which matches with the projected content from the parent component.

Suppose if didn't mention the select attribute then the non-matching content will will projected into that placeholder.

This is how the multi-slot projection looks like.

![Multi Slot Projection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no0u6cgwm4kimmo58bcy.PNG)

### Conditional Content Projection:

Let's say we have a situation where we need to project content based on certain condition then we can achieve it with conditional content projection.

But in such scenarios it is recommended to use the **ng-template** than the **ng-content**. The reason is Angular will always instantiate the content which is projecting even if the content is not rendered, but **ng-template** will instantiate only when the content is rendered.

### **ngProjectAs**:

Suppose if there is a situation you want to project certain content which is part of another element say for example content inside the **ng-container** then we can make use of the attribute ngProjectAs. Let' see with an example

> parent-component.html

```html
<cp-multi-slot>
  <ng-container ngProjectAs="complex-ele">
    <h2>This the Demo of Complex content projection</h2>
    <p>Simple Demo of complex content projection using ngProjectAs</p>
  </ng-container>
  <div another-ele>
    <p>This is another element to project into component</p>
  </div>
</cp-multi-slot>
```

> component where the dynamic content projected

```html
<p>Complex Multi-slot Projection</p>
<ng-content select="['complex-ele']"></ng-content>
<ng-content select="['another-ele']"></ng-content>
```