Skip to main content

6. Content Projection

Reusability is very important in programming. Anything we can do to reduce duplication of code should be done.

With content projection, we can create components whose reusable pieces are limited to just the external portion of the component and the inner pieces can be different base on the needs of our application

  1. Content Projection
  2. Multiple Slot Content Projection

1. Content Projection

Content projection

No need to reimplement common functionnality such as positionning logic. We need to use the <ng-content> tag in our template

import { Component, Input }  from '@angular/core';

@Component({
selector: 'app-collapsible-section',
template: `
<div (click)="toggleContent()">
<h4>{{title}}</h4>
<ng-content *ngIf="visible"></ng-content>
</div>`
})
export class CollapsibleSectionComponent implements OnInit {
@Input() title: string,
visible: boolean = true;

toggleContent() {
this.visible = !this.visible;
}
}

In our parent component's HTML

<app-collapsible-section [title]="title">
<h6>{{session.presenter}}</h6>
<span>Duration: {{session.duration}}</span>
<span>Level: {{session.level}}</span>
<p>{{session.abstract}}</p>
<app-collapsible-section>

2. Multiple Slot Content Projection

Multiple slot content projection

To use multiple content projection slot, we need to use <ng-content> along with a select attribute to specify which slot is used for which content. The select attribute can use any CSS selector.

In the following example we use the attribute selector which is a common practice to target specific elements while avoiding conflicting styles that classes could potentially cause.

import { Component, Input }  from '@angular/core';

@Component({
selector: 'app-collapsible-section',
template: `
<div (click)="toggleContent()">
<h4>
<ng-content select="[well-title]"></ng-content>
</h4>
<ng-content *ngIf="visible" select="[well-body]"></ng-content>
</div>`
})
export class CollapsibleSectionComponent implements OnInit {
visible: boolean = true;

toggleContent() {
this.visible = !this.visible;
}
}

In our parent component's HTML

<app-collapsible-section [title]="title">
<div well-title>
{{session.name}}
<i *ngIf="session.voters.length > 3" class="glyphicon glyphicon-fire"></i>
</div>
<div well-body>
<h6>{{session.presenter}}</h6>
<span>Duration: {{session.duration}}</span>
<span>Level: {{session.level}}</span>
<p>{{session.abstract}}</p>
</div>
<app-collapsible-section>