Angular
allows us to create the interface of the website based on a combination of many different components and in order to help developers create components with high reusability, angular has created a mechanism to help them. We embed the external template (html) into the components, this mechanism is called the content projection
.
ng-content
The content projection
mechanism is implemented via the ng-content
tag provided by Angular. If we put the <ng-content></ng-content>
tag in the template ( html
) file of component A
, we can pass any html tag or any set of html tags into component A
then Those html tags will be rendered where <ng-content></ng-content>
is placed in the template of component A
a.component.html
1 2 3 4 5 6 7 8 9 10 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__header <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> header của component a <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__body <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
Before I embed another template into component A
1 2 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-a</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-a</span> <span class="token punctuation">></span></span> |
Results :
When I embed html tags into component A
1 2 3 4 5 6 7 8 9 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-a</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> content bên ngoài component-a <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token punctuation">></span></span> content bên ngoài component-a <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-a</span> <span class="token punctuation">></span></span> |
Results :
We can also embed one or more other component A
into component A
1 2 3 4 5 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-a</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-b</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-b</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-c</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-c</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-a</span> <span class="token punctuation">></span></span> |
Results :
Using multiple ng-content tags for the same component
You can also set multiple tags ng-content
in the same template of a component, each card ng-content
in a different location, allowing other developers to embed multiple templates in different locations in your component,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__header <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> header của component a <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__body <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> body <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__footer <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> footer <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
However, since Angular is unable to distinguish which part of the template will render at the position of which ng-content
tag, it will render the external template in place of the last ng-content
tag in component A
‘s template.
1 2 3 4 5 6 7 8 9 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-a</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> body-content <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> nội dung phân body <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> footer-content <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> nội dung phần footer <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-a</span> <span class="token punctuation">></span></span> |
Results :
selector
To distinguish different ng-content
tags, we can pass selector
(like selector
when you know css for html tags) to select
property of different ng-content
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__header <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> header của component a <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__body <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> body <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- tìm thẻ html có class chứa body-content --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token attr-name">select</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> .body-content <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__footer <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> footer <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- tìm thẻ html có class chứa footer-content --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token attr-name">select</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> .footer-content <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
Results :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__header <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> header của component a <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__body <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> body <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- tìm thẻ html có tên là main --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token attr-name">select</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> main <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> component-a__footer <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h3</span> <span class="token punctuation">></span></span> footer <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h3</span> <span class="token punctuation">></span></span> <span class="token comment"><!-- tìm thẻ html có tên là footer --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> ng-content</span> <span class="token attr-name">select</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> footer <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> ng-content</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> |
Embed the template in component A
:
1 2 3 4 5 6 7 8 9 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> app-a</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> main</span> <span class="token punctuation">></span></span> nội dung phân body <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> main</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> footer</span> <span class="token punctuation">></span></span> nội dung phần footer <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> footer</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> app-a</span> <span class="token punctuation">></span></span> |
Results :
There are a few things that you should keep in mind:
select
not an input ofng-content
so<ng-content [select]="'main'"></ng-content>
will be the same as<ng-content></ng-content>
.select
n’t handle spaces, so you can’t write complex selectors like when you query in css.
Benefits of applying content injection
Creating a component that allows embedding external templates into that component’s template will help us reuse a template in many different layouts, especially those layouts that share a part of the outer frame, but the internal Yes, there are many differences.
Although ng-content
has many effects, it still has one weakness: we cannot access the properties or methods of the components passed in ng-content
.
Epilogue
Sometimes instead of using if else
to render layouts for different cases, using content inject
is a better option, it will reduce the logical burden on the components and increase reuse. them. I wish you a happy and effective working day. Cheer!