DEV Community

Cover image for Angular content projection - how to project views
Tomasz Flis
Tomasz Flis

Posted on

Angular content projection - how to project views

Introduction

The angular framework is used to develop single-page applications. Its views are a combination of components, including the smallest one, like, for example, buttons up to whole pages. Content projection is a technology that allows us to project one component into another. This article is about how we can project and conditionally display parts of the view into other ones.

Ng-content

ng-content is the mostly used angular feature to nest components. The easiest example would be:

<app-parent>
    <p>I will be nested!</p>
</app-parent>
Enter fullscreen mode Exit fullscreen mode

And template of AppParent:

<div class="wrapper">
    <ng-content></ng-content>
</div>
Enter fullscreen mode Exit fullscreen mode

So the end result will be:

<app-parent>
    <div class="wrapper"><p>I will be nested!</p></div>
</app-parent>
Enter fullscreen mode Exit fullscreen mode

We can have more than one ng-content element in our component, and we can distinguish their usage by adding a select attribute to it with the query selector as a value.
Example usage:

<div class="wrapper"><ng-content></ng-content></div>
<div class="wrapper-2">
   <ng-content select=".for-second-wrapper"></ng-content></div>
Enter fullscreen mode Exit fullscreen mode

And then we can use it:

<app-parent>
    <div class="wrapper"><p>I will be nested!</p></div>
    <div class=".for-second-wrapper">
        <p>I will be as next!</p>
    </div>
</app-parent>
Enter fullscreen mode Exit fullscreen mode

So the result will be:

<app-parent>
    <div class="wrapper"><p>I will be nested!</p></div>
    <div class="wrapper-2">
       <div class=".for-second-wrapper">
           <p>I will be as next!</p>
       </div> 
    </div>
</app-parent>
Enter fullscreen mode Exit fullscreen mode

NgIf, NgFor, NgSwitch

Sometimes we want to conditionally display one or another content. To do that, we can use the ngIf directive. As a value, it expects a boolean set to true displays content and removes it from the DOM when the value is false. An example of usage can be:

<p *ngIf="isLoggedIn">I am logged in!</p>
Enter fullscreen mode Exit fullscreen mode

And with the value:

isLoggedIn = true;
Enter fullscreen mode Exit fullscreen mode

In Angular, a special HTML element can be used to keep content and display it in other places. That element is ng-template. It can be used with the combination of ngIf to display when the value is false. According to the above example:

<p *ngIf="isLoggedIn; else notLoggedIn">I am logged in!</p>
<ng-template #notLoggedIn>
    <p>I am NOT logged in!</p>
</ng-template>
Enter fullscreen mode Exit fullscreen mode

#name_of_element like #notLoggedIn is a template reference that can be used to select concrete HTML elements.

We can use the ngFor directive to display the list of elements. The example:

<ul>
   <li *ngFor="let user of users">{{user}}</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

And the ts:

users = ['John', 'Tom', 'Merry'];
Enter fullscreen mode Exit fullscreen mode

It iterates through provided lists and puts each item under the variable. The result above will be:

<ul>
   <li>John</li>
   <li>Tom</li>
   <li>Merry</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

To access the index of each element, we can use the index variable:

<ul>
   <li *ngFor="let user of users; let i = index">
      {{user}}
   </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

There are also boolean variables named odd and even, which can make a difference between the following items on the list.
We can use variables with the respective names first and last to check if the given item is first or last.
A combination of all the above could be:

<ul>
   <li *ngFor="let user of users; let i = index; let first = first; let last = last; let odd = odd; let even = even">
      {{user}}
      <p *ngIf="first">I am first</p>
      <p *ngIf="last">I am last</p>
      <p *ngIf="odd">I am odd</p>
      <p *ngIf="even">I am even</p>
   </li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Similar to JavaScript, we can use switch. In HTML, it is a combination of ngSwitch and ngSwitchCase, for example:

    <div [ngSwitch]="userType">
        <div *ngSwitchCase="'ADMIN'">
            I am ADMIN
        </div>
        <div *ngSwitchCase="'MODERATOR'">
            I am MODERATOR
        </div>
        <div *ngSwitchCase="'STANDARD'">
            I am STANDARD
        </div>
        <div *ngSwitchDefault>
           I am NOT KNOWN OR DEFAULT
        </div>
    </div>
Enter fullscreen mode Exit fullscreen mode

And ts:

userType: 'ADMIN' | 'MODERATOR' | 'STANDARD' = 'STANDARD';
Enter fullscreen mode Exit fullscreen mode

Summary

Angular has a robust content projection mechanism that allows us to combine rendered content combinations. You can visit the official documentation for details.

Top comments (1)

Collapse
 
pbouillon profile image
Pierre Bouillon

I regret Angular not having a fallback for the projected values

For example, If I want app-parent to display something if nothing is projected, this can be a bit cumbersome compared to other frameworks such as Svelte

Here’s to hoping it will be improved as part of the focus the dev team has on the component authoring format for the next versions! πŸ™Œ