In this article, we will explore how to use ng-content
for content projection to create flexible and reusable components. The
ng-content
element is a placeholder for inserting external or dynamic content. The parent component passes external content to the child component, and when Angular parses the template, the external content is inserted in the child component template where ng-content
appears.
We can use content projection to create reusable components. These components have similar logic and layout and can be used in many places. Generally we often use it when encapsulating some public components. [Related tutorial recommendations: "angular tutorial"]
In order to understand why ng-content
should be used for content projection, First let's create a very common button component.
btn.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-btn', templateUrl: './btn.component.html', styleUrls: ['./btn.component.scss'], }) export class BtnComponent { constructor() {} onClick($event: any) { console.log($event); } }
btn.component.html
<button (click)=onClick($event)> Click Me </button>
In this component, the text of the button is always Click Me
, if Do we want to pass different text in? You may think of the most commonly used @Input
decorator, but what if we don’t just want to pass in text, but a piece of html? At this time, you need to use the protagonist of this article: ng-content
.
The most basic form of content projection is Single Slot Content Projection. Single slot content projection means creating a component into which we can project a component.
To create a component that uses single-slot content projection, we just need to make some simple modifications to the component above: replace Click Me
with <ng-content> </ng-content>
.
btn.component.html
<button (click)=onClick($event)> <ng-content></ng-content> </button>
Where the btn component is used:
<app-btn>Cancel</app-btn> <app-btn><b>Submit</b></app-btn>
In<app-btn></app-btn># The content in ## will be passed to the btn component and displayed in
ng-contnet.
ng-content is more powerful than this. A component can have multiple slots, and each slot can specify a CSS selector that determines what content goes into that slot. This mode is called
Multi-Slot Content Projection. Using this mode, we must specify where we want the projected content to appear. This can be accomplished by using the select attribute of
ng-content.
ng-content element where you want the projected content to appear.
select attribute to the
ng-content element. The selectors used by Angular support any combination of tag names, attributes, CSS classes, and
:not pseudo-classes.
<div class="card"> <div class="header"> <ng-content select="header"></ng-content> </div> <div class="content"> <ng-content select="content"></ng-content> </div> <div class="footer"> <ng-content select="footer"></ng-content> </div> </div>
<app-card> <header> <h1>Angular</h1> </header> <content>One framework. Mobile & desktop.</content> <footer><b>Super-powered by Google </b></footer> </app-card> <app-card> <header> <h1 style="color:red;">React</h1> </header> <content>A JavaScript library for building user interfaces</content> <footer><b>Facebook Open Source </b></footer> </app-card>
app- Is there content in card that does not belong to header, content, and footer? For example, if you use the
app-card component as follows:
<app-card> <header> <h1>Angular</h1> </header> <div>Not match any selector</div> <content>One framework. Mobile & desktop.</content> <footer><b>Super-powered by Google </b></footer> <div>This text will not not be shown</div> </app-card>
div are not rendered in page, in order to solve this problem, we can add a
ng-content tag without any
selector in the component. All content that does not match any other slot will be rendered in this one.
<div class="card"> <div class="header"> <ng-content select="header"></ng-content> </div> <div class="content"> <ng-content select="content"></ng-content> </div> <div class="footer"> <ng-content select="footer"></ng-content> </div> <ng-content></ng-content> </div>
ng-container to wrap some content and pass it to in the component. Most of the time it's because we need to use structural directives like
ngIf or
ngSwitch etc. For example, headers are passed to the card component only under certain circumstances.
ng-container.
<app-card> <ng-container> <header> <h1>Angular</h1> </header> </ng-container> <content>One framework. Mobile & desktop.</content> <footer><b>Super-powered by Google </b></footer> </app-card>
ng-container, the header part is not rendered to the slot we want to render, but is rendered to
ng- which does not provide any selector. content in.
ngProjectAs attribute.
ng-container, and you can render it according to our expectations.
<app-card> <ng-container ngProjectAs='header'> ... </app-card>
Programming Teaching! !
The above is the detailed content of A brief discussion on how Angular uses ng-content for content projection. For more information, please follow other related articles on the PHP Chinese website!