Angular Content projection

Indira Raghavan
3 min readNov 2, 2020

Powerful way to build reusable components

To better understand ng-content projection let’s talk about the design problem we are trying to solve. Let’s say we have a basic card design — Title, Text and submit button. Based on the content of the website we are about to build, let’s say we have 3 different types of templates:

  1. A card with just plain information text.
  2. A card with bulleted list(or numbered list) of information.
  3. A card with text and image(perhaps)

Does that mean we build 3 different components? For each of the above scenario? But, our basic card design is the same. Same colors, same borders, same text font-size etc. Not efficient to build 3 different when we can make one Card component a dynamic component. Can we build a Card-component that will project different content only for the text section (card body). Yes we can! And that’s what I will show how to build.

Let’s start with basic Angular app, named ContentProjection

npm i @angular/cli -gng new ContentProjection

For ease of explaining the concept, I have added bootstrap styles to angular.json file

"styles": [
"node_modules/bootstrap/dist/css/bootstrap.css",
"src/styles.scss"
]

Let’s create a Card & Display components: Card is our reusable component, Display is going to display the card component with different content mentioned above.

ng generate component Card
ng generate component Display

Paste the following html for card.component.html

<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<ng-content></ng-content>
<a href="#" class="card-link">Card link</a>
</div>
</div>

This is the basic card from bootstrap site. It just have the text section. As mentioned above we are going to have the title and link as common factors across all cards on the site. The middle section(bolded section) will change based on what we wish to project. Now let’s go to display component and add the card component with different content inside the card body.

Paste the following html into display.component.html

<div class="container">
<div class="row mt-5">
<div class="col-4">
<app-card>
<p class="card-text">Some quick example text to
build on the card title and make up the
bulk of the card's content.</p>
</app-card>

</div>
<div class="col-4">
<app-card>
<ul> Sample list items:
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</app-card>

</div>
<div class="col-4">
<app-card>
<h5 class="card-title text-success">Success card
title</h5>
<p class="card-text text-danger">Texts with warning
or success color system to bring user's
attention to it</p>
</app-card>

</div>
</div>
</div>

If you notice the usage above, all three references of <app-card></app-card> is different. Projected content is different for each usage, though all references the same Card component.

Result for the above implementation

In conclusion:

Angular directive ng-content helps solve a design problem where template inside a component is provided as an input instead of hiding the template inside the component itself. This simplifies and solves a lot of design problems. Identifying common templates and isolating the component, helps in focusing the actual varying template.

--

--