Ng-Content & Content Projection in Angular

In this guide let us explore how to use ng-content to add external content (content projection) in the Template. We know how to use @Input decorator to pass data from the parent component to the child component. But it is only limited to data. We cannot use that technique to pass the content which includes the HTML elements, CSS, etc to the child component. To do that we have to make use of content projection.

Content projection is a way to pass the HTML content from the parent component to the child component. The child component will display the template in a designated spot. We use the ng-content element to designate a spot in the template of the child component. The ng-content also allows us to create multiple slots using the selector attribute. The parent can send different content to each slot.

Applies to: Angular 2 to the latest edition of i.e. Angular 8. Angular 9, Angular 10

What is ng-content

The ng-content tag acts as a placeholder for inserting external or dynamic content. The Parent component passes the external content to the child component. When Angular parses the template, it inserts the external content where ng-content appears in the child component’s template

We can use content projection to create a reusable component. The components that have similar logic & layout and can be used in many places in the application.

Take an example of a card component. It has a header section, footer section & body section. The contents of these sections will vary. The ng-content will allow us to pass these sections to the card component from the parent component. This enables us to use the card component at many places in the app.

Without ng-content

To understand how content projection using ng-content works, first let us build a simple button component without ng-content.

Create a new Angular application. Add a new component btn.component.ts.It is a simple component, which displays a button with the caption Click Me

Now go to the app.component.html.

In the code above, we have two buttons with the caption Click Me show up on the screen as expected.

What if we want to change the caption from the parent. We can do that using the @Input property. But using @input, we can only set the caption of the button. But we cannot change the look and appearance of the caption.

ng-content Example

Create a new component FancyBtnComponent. Copy all the codes from BtnComponent except for one change. Remove Click Me and add <ng-content> </ng-content> instead. This tag acts as a placeholder. You can also think of it as an argument to the component. The parent component must supply the argument

Now open the app.component.html

The content between <app-fancybtn> </app-fancybtn> is passed to our FancyBtnComponent. The component displays it in place of ng-content.

The advantage of such a solution is that you can pass any HTML content.


Best Angular Books
The Top 8 Best Angular Books, which helps you to get started with Angular  

ng-content Example

Events

The events like click, input, etc bubble up. Hence can be captured in the parent as shown below

But if you have more than one button, then you may have to inspect the $event argument to check, which button responsible for the event.

Custom Events

You can create custom events using the @output as shown in below

In parent component

Multiple Projections using ng-content

The button example is a very simple example. The ng-content is much more powerful than that. It allows us to create multiple slots in the template. Each slot must define a selector. You can think this as a multiple arguments to the component

In the parent component we can create different contents and each of those contents can be projected into any of those slots depending on their selector. To implement this we make use of the ng-content Select attribute. The select attribute is a CSS Selector

Example of ng-content select attribute

For Example, create a new component card.component.ts

In the above example, we have three ng-content slots, each have a selector header,content & footer

Now open the app.component.html add the following code

Select attribute is a CSS selector

You can use any CSS selector as the select attribute. Like class, element, id attributes, etc. For Example, the above card component using the CSS class

And in the component, we use it as

Similarly, you can use the various CSS Selectors as shown below

ng-content without selector catches all

Now, in the following example, the last paragraph does not belong to any ng-content slots. Hence ng-content will not project the last para as it cannot determine where to add.

To solve the above issue, we can include ng-content without any selector. It will display all the content, which cannot be projected into any other slots.

ngProjectAs

Sometimes it becomes necessary to wrap the component using the ng-container. Most of the time when you use a structural directive like ngIf or ngSwitch.

In the following example, we enclosed the header inside the ng-container.

Because of the ng-container, the header section is not projected to the header slot. Instead, it is projected to the ng-content slot which does not have a selector set.

To help in such a scenario, you can make use of ngProjectAs attribute as shown below.

Source Code

References

Summary

The ng-content allows us to add the external content in the Template. Unlike @Input, using ng-content we can pass the data which includes the HTML elements, CSS, etc, This is also known as content projection. We can also define different slots using the selector attribute. These slots allow us to add different content to different slots.

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top