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! ๐Ÿ™Œ