Angular content projection - how to project views
Tags: webdev, javascript, beginners, angular
Published: 2023-08-19 16:23:10

### 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:
```html
<app-parent>
    <p>I will be nested!</p>
</app-parent>
```
And template of `AppParent`:
```html
<div class="wrapper">
    <ng-content></ng-content>
</div>
```
So the end result will be:
```html
<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:
```html
<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:
```html
<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:
```html
<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:
```html
<p *ngIf="isLoggedIn">I am logged in!</p>
```
And with the value:
```ts
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:
```html
<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:
```html
<ul>
   <li *ngFor="let user of users">{{user}}</li>
</ul>
```
And the ts:
```ts
users = ['John', 'Tom', 'Merry'];
```
It iterates through provided lists and puts each item under the variable. The result above will be:
```html
<ul>
   <li>John</li>
   <li>Tom</li>
   <li>Merry</li>
</ul>
```
To access the index of each element, we can use the `index` variable:
```html
<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:
```html
<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:
```html
    <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:
```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](https://angular.io/guide/content-projection) for details.