Today, when I was doing Angular development, a knowledge point caught my attention:
When inspecting the DOM, I see that ngcontent is applied to the element by Angular. Hmm... If they contain the elements in the final DOM, what is the use of \<ng-container>? At the time I was confused about the difference between \<ng-container> and \<ng-content>.
In the process of seeking to know the answer to my question, I discovered the concept of \<ng-template>. To my surprise, there is another confusing concept: *ngTemplateOutlet. I started my journey, seeking clarification of two concepts, but now I have four, which sound almost the same!
Have you encountered this situation? If yes, then you have come to the right place. Therefore, without further ado, let us introduce them one by one.
1. \<ng-template>
As the name implies, \<ng-template> is a template element, and Angular is used with structural directives ( ngIf, ngFor, [ngSwitch] and custom directives).
These template elements only work when there are structural instructions. Angular wraps the host element (the element to which the directive applies) in \<ng-template> and uses \<ng-template> in the completed DOM by replacing it with diagnostic comments.
Consider a simple *ngIf example:
Shown above is the Angular interpretation of *ngIf, which is the actual code after removing the syntactic sugar. Angular puts the host element of the application instruction in \<ng-template> and keeps the host as it is. The final DOM is similar to what we saw at the beginning of this article:
2. \<ng-container>
The reason many of us write this code is that we cannot use multiple structural directives on a single host element in Angular. Now this code works fine, but if item.id is a false value that may not be needed, it will introduce a few extra empty \<div> in the DOM.
People may not care about simple examples like this, but for large applications with complex DOM (displaying tens of thousands of data), this can become cumbersome, because elements may have listeners attached to them. The listener still exists in the DOM to listen for events.
Even worse is the level of nesting that must be performed to apply styles (CSS)!
Don't worry, we have \<ng-container> to rescue!
Angular \<ng-container> is a grouping element that does not interfere with style or layout, because Angular does not place it in the DOM.
Rewrite using ng-container.
It can be understood that the div tag is placed in the void container ng-container. When the Boolean value of the *ngIf directive of the div is false, the void container and the div tag inside will not be generated at all.
In the finally rendered HTML code, there are no extra empty div tags:
Best practice: When we just want to apply multiple structural directives without introducing any additional elements in our DOM, we should use \<ng-container>.
3. \<ng-content>
They are used to create configurable components. This means that the components can be configured according to the user's needs. This is the well-known content projection: Content Projection. The components used in the published library use \<ng-content> to make themselves configurable.
Consider a simple \<project-content> component, the following figure is its own HTML definition:
Obviously, the footer area allows dynamic configuration of content.
The following figure shows how to dynamically inject custom footer content into the footer area. This usage is called single projection.
\<project-content> The HTML content passed in the start and end tags of the component is the content to be projected. This is what we call content projection. The content will be presented in \<ng-content> in the component that provides the content projection function.
This allows users of the \<project-content> component to pass any custom footer within the component and control exactly how they want it to be presented.
Multiple Projections
What if you can decide what content should be placed where? In addition to projecting each content into a single \<ng-content>, you can also use the select attribute of \<ng-content> to control how the content is projected. It needs an element selector to decide what content to project in a particular \<ng-content>.
That's it:
We modified the definition of \<project-content> to perform multi-content projection. The select attribute selects the type of content that will be presented in a specific <ng-content>. Here we first choose to render the title h1 element. If the projected content does not have an h1 element, it will not render any content. Similarly, the second option finds the div. The rest of the content is presented in the last \<ng-content>, there is no choice.
How to consume this component with select attribute that allows multiple projections? The method is as follows:
4. *ngTemplateOutlet
*ngTemplateOutlet is used in two scenarios:
- Insert a common template in each part of the view, regardless of loops or conditions
- Make highly configured components.
Template reuse
Consider a view where you must insert templates in multiple locations. For example, the company logo to be placed on the website. We can achieve it by writing a template for the logo once and reusing it anywhere in the view.
The following is the code snippet:
As you can see, we only wrote the logo template once and used it 3 times with one line of code on the same page!
Customizable components
*The second use case of ngTemplateOutlet is a highly customized component. Consider our previous \<project-content> component example with some modifications:
The above is a modified version of the \<project-content> component, which accepts three input attributes-headerTemplate, bodyTemplate, and footerTemplate. The following is a snippet of project-content.ts:
The input attributes used in the template file, headerTemplate, bodyTemplate and footerTemplate attributes are defined in the Component file.
What we are trying to achieve here is to display the header, body and footer received from the parent component of \<project-content>. If none of these are provided, our component will display the default template in its place. Therefore, a highly customized component was created.
To use our recently modified component:
This is how we pass template references to our components. If any of them fail, the component will render the default template.
ng-content vs. *ngTemplateOutlet
They can all help us realize highly customized components, but which one to choose and when to choose?
It can be clearly seen that if it is not provided, *ngTemplateOutlet provides us with more capabilities to display the default template
This is not the case with ng-content. It presents the content as it is. At best, you can split the content with the help of the select attribute and present them in different positions of the view. You cannot conditionally render the content in ng-content. You must display the content received from the parent and cannot make a decision based on the content.
However, the choice between the two depends entirely on your use case. At least now we have a new weapon in our arsenal, *ngTemplateOutlet. In addition to the functions of ng-content, it also provides more control over content!
More original articles by Jerry, all in: "Wang Zixi":
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。