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>
And template of AppParent:
<div class="wrapper">
<ng-content></ng-content>
</div>
So the end result will be:
<app-parent>
<div class="wrapper"><p>I will be nested!</p></div>
</app-parent>
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>
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>
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>
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>
And with the value:
isLoggedIn = true;
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>
#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>
And the ts:
users = ['John', 'Tom', 'Merry'];
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>
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>
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>
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>
And ts:
userType: 'ADMIN' | 'MODERATOR' | 'STANDARD' = 'STANDARD';
Summary
Angular has a robust content projection mechanism that allows us to combine rendered content combinations. You can visit the official documentation for details.