Content Projection in Angular
Tags: angular, beginners, typescript, webdev
Published: 2022-01-22 18:29:37

Today we will learn about a very important concept called `Content Projection`. It's very useful concept and helps to make an application dynamic.

Let's dive in by creating our playground first -
Lets create a component called `my-cards` and use it in the `app.component.html` file (Hint 😉 using the selector)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p3svdhrx92pevx5y7051.PNG)

---

Now lets try out a simple exercise. Add the below code in the `app.component.html` file -
```
<app-my-cards>
    <span>
        This is some content in between the card selector!
    </span>
</app-my-cards>
```
If you open the browser to check the output you will see the text you typed in between the selector i.e. `This is some content in between the card selector!` is not visible/ not getting displayed.

The output -
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n881ut4xqdv6lzoh70xf.PNG)

So the span element which is the child of the selector is the `content` and it's also the child element. So if we combine both the term we get `content child`. The span element is the content child.

Now as we saw earlier in the demo the content child is not getting displayed. So in order to display the content child we need to project it. Or in simple term we need to have a special placeholder (in the child component - `MyCardsComponent`) which will catch/ receive the value and display it.

This special placeholder is `ng-content`.

So now let's update the `MyCardsComponent`'s template to have- 
```
<ng-content></ng-content>
```
and now you will see the below output -
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vxij4i958mq7tryee6x.PNG)
So what exactly happens ?
The child content here in this case the `span` gets projected in the `ng-content`. So `ng-content` acts as a placeholder.

Now what if you need multiple placeholders? For example you will pass a content that would sit on the card-header another content as the card-body and another in the card-footer???
For that we need to use something called `select` - It is very powerful.
The select can accept a `class`, `id`, `attribute` or an `element`. Confused?

Lets see a quick example. Paste in the below code in the `app.component.html` file -

```
<app-my-cards>
    <header>Card Header</header>
    <span id='card-sub-header'>Card Sub Header</span>
    <div class="card-body">
        This is a card Body!!!
    </div>
    <footer title="card-footer">
        Card Footer.
    </footer>
</app-my-cards>
```
And in the `my-cards.component.html` file i.e. `MyCardsComponent`'s template file paste in the below code -
```
<ng-content select='header'></ng-content>
<ng-content select='#card-sub-header'></ng-content>
<ng-content select='.card-body'></ng-content>
<ng-content select='[title]'></ng-content>
```
The output - 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g9rzv54uxcja2qzrfae5.PNG)

So the 1️⃣ first `ng-content` has a selector which matches an element/ tag - the header tag
2️⃣ Second `ng-content` selector matches an id `card-sub-header`
3️⃣ Third `ng-content` selector matches a class `card-body`
4️⃣ Fourth `ng-content` selector matches an attribute `title`

There can also be a scenario where instead of using header tag (in the above example) you need to use a div tag like below -
```
<app-my-cards>
    <div >Card Header</div>
    <span id='card-sub-header'>Card Sub Header</span>
    <div class="card-body">
        This is a card Body!!!
    </div>
    <footer title="card-footer">
        Card Footer.
    </footer>
</app-my-cards>
```
Then the header will not work right? And suppose you don't have the option to change the card component also. Then what's the solution ???

`ngProjectAs` comes to the rescue!!!

Paste in the below code -
```
<app-my-cards>
    <div ngProjectAs='header'>Card Header</div>
    <span id='card-sub-header'>Card Sub Header</span>
    <div class="card-body">
        This is a card Body!!!
    </div>
    <footer title="card-footer">
        Card Footer.
    </footer>
</app-my-cards>
```
Here you can see the first line is the `div` tag. And we have used `ngProjectAs='header'`. In this case Angular will consider the selector as `header` and the output will work as it is.

That's all for now.

Hope you enjoyed reading the post

If you liked it please _like_ ❤️ _share_ 💞 _comment_ 🧡.

Coming up `ContentChild` and `ContentChildren`.
So stay tuned.

I will be [tweeting](https://twitter.com/Anubhab_0905) more on `Angular` `JavaScript` `TypeScript` `CSS` tips and tricks.

So hope to see you there too 😃

**_Cheers_** 🍻 
_Happy Coding_