Home  >  Article  >  Web Front-end  >  A brief discussion on how Angular uses ng-content for content projection

A brief discussion on how Angular uses ng-content for content projection

青灯夜游
青灯夜游forward
2021-07-02 11:00:592454browse

A brief discussion on how Angular uses ng-content for content projection

In this article, we will explore how to use ng-content for content projection to create flexible and reusable components. The

ng-content

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"]

Do not use content projection

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.

Single Slot Content Projection

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 d553bd28b5bbbbd4b6fb4990edbabbf0 78e68693bbc3a4be56286441c90e88e6.

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>

In4f5ea333ca342b306353367e241915b03e56165a02e29eb7b68166825115687f# The content in ## will be passed to the btn component and displayed in ng-contnet.

Multi-slot content projection

The btn component above is very simple, but in fact

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.

To create a component that uses multi-slot content projection, you need to do the following:

  • Create a component.

  • In the component template, add the

    ng-content element where you want the projected content to appear.

  • Add the

    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.

Let’s create a more complex card component.

card.component.html

<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>

Where the card component is used:

app.component.html

<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>

If in

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.component.html

<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>

, you will find that both

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.

card.component.html

<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>

ngProjectAs

In some cases, we need to use

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.

In the example below, we wrap the header in

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>

Due to the existence of

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.

In this case, we can use the

ngProjectAs attribute.

Add this attribute to the above

ng-container, and you can render it according to our expectations.

<app-card>
  <ng-container ngProjectAs=&#39;header&#39;>
    ...
</app-card>

For more programming-related knowledge, please visit:

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!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete