Understanding Content Projection in Angular
• • 3 min readContent projection, what is it?
Content projection (also known as transclusion) is a way to import HTML content from outside the component and insert that content into the component's template in a designated spot.
Therefore, using content-projection you can obtain the result shown in the following image.
![](http://www.carloscaballero.io/content/images/2019/06/image.png)
Notice that the component works like a mirror. Another more complicated example in the one shown in the following image in which a letter with user data is being configured.
![](http://www.carloscaballero.io/content/images/2019/06/image-1.png)
I saw a ng-container, what is that?
The Angular ng-container is a grouping element (syntax element) that doesn't interfere with styles or layout because Angular doesn't put it in the DOM.
And we can use structural directives with it.
Structural... What?
A Structural directive changes the DOM layout by adding, removing or manipulating DOM elements.
And then can I...?
![](http://www.carloscaballero.io/content/images/2019/06/image-2.png)
where am-icon
is the following component:
import { Component, ViewChild, ElementRef, AfterContentChecked } from '@angular/core';
@Component({
selector: 'am-icon',
template: `
<!-- A bit tricky... 🤟🏻 -->
<span #content [hidden]="true"><ng-content></ng-content></span>
<ng-container [ngSwitch]="icon">
<ng-container *ngSwitchCase="'fire'">🔥</ng-container>
<ng-container *ngSwitchCase="'heavy'">🤟🏻</ng-container>
<ng-container *ngSwitchDefault>🖖🏻</ng-container>
</ng-container>
`,
})
export class IconComponent implements AfterContentChecked {
icon: string;
@ViewChild('content') content: ElementRef<HTMLSpanElement>;
// Using OnPush we need to run change detection by hand
ngAfterContentChecked() {
if (this.icon !== this.content.nativeElement.textContent) {
this.icon = this.content.nativeElement.textContent;
}
}
}
The result is an icon instead of four, just as we expected. 💔
![](http://www.carloscaballero.io/content/images/2019/06/image-3.png)
How does ng-content work?
- ng-content doesn't produce content. It simply projects the existing content
- consistency of expectations 👀
- performance 🔥
- Following the previous rule, it can neither create nor destroy components projected (lifecycle).
- Only the last ng-content projects the content.
And... what can I do? Here ng-template comes to the rescue...
![](http://www.carloscaballero.io/content/images/2019/06/image-5.png)
What is a ng-template?
As the name suggests, it is a template element, a model which you can instantiate, hence you can set a template as a component's input, which is pretty useful.
The asterisk (*) syntax
The asterisk is syntactic sugar for something a bit more complicated.
You usually see with: *ngIf, *ngFor, *anyDirective, ...
![](http://www.carloscaballero.io/content/images/2019/06/image-6.png)
Then our repeat component?
![](http://www.carloscaballero.io/content/images/2019/06/image-7.png)
![](http://www.carloscaballero.io/content/images/2019/06/image-8.png)
Explain me what that ngTemplateOutlet is!
The ngTemplateOutlet directive receives a ng-template and it's responsible for create the instance and insert it into the DOM.
![](http://www.carloscaballero.io/content/images/2019/06/image-9.png)
Yeah, context like in JS!
We can give an object to the instance, which is created by the ngTemplateOutlet, of your ng-template. That object can contain whatever you want to pass to your template. Here, we expose the magic of a lot of library components (datatables, angular-material, ng-bootstrap, ...).
We can do awesome things!
![](http://www.carloscaballero.io/content/images/2019/06/image-10.png)
More more more...
- Presentation
- The GitHub branch of this post is https://github.com/Caballerog/ng-transclusion/