The original
As I was working on Angular development today, a knowledge point caught my eye:
When I examine the DOM, I see NgContent being applied to the element by Angular. HMM… What’s the use of \<ng-container> if they contain elements in the final DOM? At the time, I was confused about the difference between \<ng-container> and \<ng-content>.
In my quest to find out the answer to my question, I came across the concept of \<ng-template>. To my surprise, there is another confusing concept: *ngTemplateOutlet. I started my journey seeking clarification on two concepts, but now I have four that sound almost the same!
Has this ever happened to you? If so, you’ve come to the right place. So, without further ado, let us introduce them all.
1. \<ng-template>
As the name implies, \
is a template element that Angular uses with structural directives (ngIf, ngFor, [ngSwitch], and custom directives).
These template elements are only useful when there are structural directives. Angular wraps the host element (to which the directive is applied) 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 unsweetened syntax. Angular places the application directive’s host element in \<ng-template> and leaves the host as it is. The resulting DOM looks something like what we saw at the beginning of this article:
2. \<ng-container>
A lot of us wrote this code because we couldn’t use multiple structure directives on a single host element in Angular. Now this code works fine, but if item.id is a dummy value that might not be needed, it introduces a few extra null \<div> into 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 troublesome because elements may have listeners attached to them that still exist in DOM listening events.
Even worse is the level of nesting that must be performed to apply styles (CSS)!
Don’t worry, we have \<ng-container> to the rescue!
Angular \<ng-container> is a grouping element that doesn’t interfere with style or layout because Angular doesn’t put it in the DOM.
Overridden using ng-container.
If the *ngIf directive of a div is false, then the empty container and the div tag will not be generated at all.
In the resulting HTML code, there are no more empty div tags:
Best practice: We should use \<ng-container> when we only want to apply multiple structure directives without introducing any extra elements into our DOM.
3. \<ng-content>
They are used to create configurable components. This means that components can be configured according to the user’s needs. This is known as Content Projection. Components used in published libraries make themselves configurable using \<ng-content>.
Consider a simple \<project-content> component with its own HTML definition below:
Obviously, the Footer area allows for dynamic configuration of content.
The following figure shows how to dynamically inject custom Footer content into the Footer area. This usage is called a single projection.
\<project-content The HTML content passed in the opening and closing tags of the > component is the content to be projected. This is what we call a content projection. The content will be rendered inside the \<ng-content> component that provides the content projection function.
This allows consumers of the \<project-content> component to pass any custom footers within the component and control exactly how they want to render it.
Multiple Projections
What if you could decide what goes 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 requires an element selector to decide what to project in a particular \<ng-content>.
That’s it:
We modified the \<project-content> definition to perform a multi-content projection. The select attribute selects the type of content to be rendered in a particular <ng-content>. Here we first select the render title h1 element. If the projected content does not have an h1 element, it will render nothing. Again, the second option looks for div. The rest of the content is rendered in the last \<ng-content> with no selection.
How do I consume this component with a select property that allows multiple projections? The method is as follows:
4. *ngTemplateOutlet
*ngTemplateOutlet is used for two scenarios:
- Insert a common template into 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 places. For example, the company logo to be placed on the site. We can do this by writing a template for the logo once and reusing it anywhere in the view.
Here’s the code snippet:
As you can see, we only wrote the logo template once and used it three times with a single line of code on the same page!
Customizable components
* The second use case for NgTemplateOutlet is a highly customized component. Consider our previous \<project-content> component example, with some modifications:
This is a modified version of the \<project-content> component that takes three input properties — HeaderTemplate, BodyTemplate, FooterTemplate. Here’s an excerpt from project-content.ts:
The input properties used in the template file, the HeaderTemplate, BodyTemplate, and FooterTemplate properties 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 neither of these is provided, our component will display the default template in its place. Therefore, a highly customized component is created.
To use our recently modified component:
This is how we pass the template reference to our component. If any of these fail, the component renders the default template.
ng-content vs. *ngTemplateOutlet
Both of them can help us achieve highly customized components, but which one and when?
As you can clearly see, *ngTemplateOutlet gives us more ability to display the default template if it is not provided.
This is not the case with ng-content. It renders the content as-is. At best, you can split the content and render it at different places in the view with the help of the select attribute. You cannot conditionally render content in an ng-content. You must display the content received from the parent, and you cannot make a decision based on the content.
However, the choice between the two is entirely up to your use case. At least we now have a new weapon in our Arsenal *ngTemplateOutlet, which provides more control over content in addition to the ng-content functionality!
More of Jerry’s original articles can be found on “Wang Zixi “: