This article will talk about content projection in angular, introduce the method of using ng-content for content projection, and understand the implementation method of conditional content projection. I hope it will be helpful to everyone. !
ng-content
Content projection1.1 <span style="font-size: 16px;">ng-content</span>
ng-content
element is a placeholder used to insert external or dynamic content symbol
. The parent component passes external content
to the child component. When Angular
parses the template, the external content will be inserted in the child component template where ng-content
appears. . [Related tutorial recommendations: "angular tutorial"]
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.
1.2 Why use content projection
Define a button component:
button-component.ts
@Component({ selector: '[appButton]', template: ` <span class="icon-search"></span> ` }) export class AppButtonComponent {}
The purpose of this button component is to add a search icon inside the button. We actually use it as follows:
<button appButton>click</button>
We found that the component will only display the search icon, and the text of the button will not be displayed. , you may think of the most commonly used @Input
decorator, but what if we don’t just want to pass in text, but a paragraph of html
? ng-content
will be used at this time.
1.3 Single Slot Content Projection
The most basic form of content projection is Single Slot Content Projection
.
Single-slot content projection refers to creating a component into which we can project a component.
Take the button component as an example to create a single-slot content projection:
button-component.ts
@Component({ selector: '[appButton]', template: ` <span class="icon-search"></span> <ng-content></ng-content> ` }) export class AppButtonComponent {}
The actual usage is as follows:
<button appButton>click</button>
It can be found that the effect of this button component is to display both the search icon and the text of the button (click). That is, the content in the middle of
is projected
to the <ng-content></ng-content>
Location. The
ng-content element is a placeholder, it does not create a real DOM element. Those custom attributes of ng-content will be ignored.
1.4 Multi-slot content projection
A component can have multiple slots
, each A slot can specify a CSS selector
, which determines what content goes into the slot. This mode is called Multi-Slot Content Projection
. Using this mode, we must specify the position where we want the projected content
to appear. This can be accomplished by using the select
attribute of ng-content
.
multiple
ng-content
tags. ng-content tag
, you need to use the select
attribute on the ng-content
tag as identification . select
Attributes support tag name
, property
, CSS class
and :not pseudo-class## Any combination of #.
tag that does not add the
select attribute will serve as the
default slot. All unmatched projected content will be projected at this
ng-content location.
button-component.ts
@Component({ selector: '[appButton]', template: ` <span class="icon-search"></span> <ng-content select="[shuxing]"></ng-content> <ng-content select="p"></ng-content> <ng-content select=".lei"></ng-content> ` }) export class AppButtonComponent {}
<button appButton> <p>click</p> <span shuxing>me</span> <span class="lei">here</span> </button>
1.5 ngProjectAs<span style="font-size: 16px;"></span>
ng-container Wrap some content and pass it to the component. Most of the time it's because we need to use structural directives like
ngIf or
ngSwitch etc. .
header in
ng-container.
@Component({ selector: 'app-card', template: ` <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> ` }) export class AppCardComponent {}
<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 into the slot we want to render. , instead it is rendered into
ng-content which does not provide any
selector.
In this case we can use the
ngProjectAs attribute.
Add this attribute to
ng-container above, and you can render it according to our expectations.
<app-card> <ng-container ngProjectAs='header'> <header> <h1>Angular</h1> </header> </ng-container> <content>One framework. Mobile & desktop.</content> <footer><b>Super-powered by Google </b></footer> </app-card>
如果你的元件需要有条件地渲染内容或多次渲染内容,则应配置该元件以接受一个 ng-template
元素,其中包含要有条件渲染的内容。
在这种情况下,不建议使用 ng-content
元素,因为只要元件的使用者提供了内容,即使该元件从未定义 ng-content
元素或该 ng-content
元素位于 ngIf
语句的内部,该内容也总会被初始化。
使用 ng-template
元素,你可以让元件根据你想要的任何条件显式渲染内容,并可以进行多次渲染。在显式渲染 ng-template
元素之前,Angular
不会初始化
该元素的内容。
2.1 <span style="font-size: 16px;">ng-container</span>
既不是一个组件,也不是一个指令,仅仅是一个特殊的tag而已。 使用 ng-container
渲染所包含的模板内容,不包含自身。
<div> <ng-container> <p>My name is wyl.</p> <p>What is you name?</p> </ng-container> </div>
<ng-container>
标签消失了,并没有起任何作用<div> <p>My name is wyl.</p> <p>What is you name?</p> </div>
遍历
或 if 判断
时,它可以承担一个载体
的作用<ul> <ng-container *ngFor="let item of items"> <li>{{ item .name}}</li> <li>{{ item .age}}</li> <li>{{ item .sex}}</li> </ng-container> </ul>
另外,ng
中常见错误之一的 for
和 if
不能写在同一标签上(在一个宿主元素上只能应用一个结构型指令),利用 ng-container
标签可以在实现功能的基础上减少层级的嵌套。
2.2 <span style="font-size: 16px;">ng-template</span>
先来看下面一段代码
<ng-template> <p> In template, no attributes. </p> </ng-template> <ng-container> <p> In ng-container, no attributes. </p> </ng-container>
浏览器输出结果是:
In ng-container, no attributes.
即 <ng-template>
中的内容不会显示。当在上面的模板中添加 ngIf
指令:
<ng-template [ngIf]="true"> <p> ngIf with a ng-template.</p> </ng-template> <ng-container *ngIf="true"> <p> ngIf with an ng-container.</p> </ng-container>
浏览器输出结果是:
ngIf with a ng-template. ngIf with an ng-container.
2.3 <span style="font-size: 16px;">ng-template</span>
和 <ng-container>
的配合使用
<ng-container *ngIf="showSearchBread; else tplSearchEmpty"> 暂时搜索不到您要的数据喔 </ng-container> <ng-template #tplSearchEmpty> 快快开始获取吧! </ng-template>
2.4 <span style="font-size: 16px;">ngTemplateOutlet</span>
插入 ng-template
创建的内嵌视图。 ngTemplateOutlet
是一个结构型指令
,接收一个 TemplateRef
类型的值;
<div *ngTemplateOutlet="tpl1"></div> <ng-template #tpl1> <span>I am span in template {{title}}</span> </ng-template>
*ngTemplateOutlet = "templateRefExp; content: contentExp "
ng-template
元素的 #ID
可空参数
content
是一个对象,这个对象可以包含一个 $implicit
的 key
作为默认值, 使用时在 模板
中用 let-key
语句进行绑定
content
的非默认字段需要使用 let-templateKey=contentKey
语句进行绑定
使用如下:
@Component({ selector: 'ng-template-outlet-example', template: ` <ng-container *ngTemplateOutlet="greet"></ng-container> <hr> <ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container> <hr> <ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container> <hr> <ng-template #greet><span>Hello</span></ng-template> <ng-template #eng let-name><span>Hello {{name}}!</span></ng-template> <ng-template #svk let-person="localSk"><span>Ahoj {{person}}!</span></ng-template> ` }) class NgTemplateOutletExample { myContext = {$implicit: 'World', localSk: 'Svet'}; }
2.5 利用 <span style="font-size: 16px;">ngTemplateOutlet</span>
进行内容投影
@Component({ selector: 'app-card', template: ` <div class="card"> <div class="header"> <ng-container *ngTemplateOutlet="headerTemplate; context: { $implicit: title, index: otherDate }"></ng-container> </div> </div> ` }) export class AppCardComponent { @ContentChild('header', { static: true }) headerTemplate: TemplateRef<any>; public title = 'Test'; public otherDate = { auth: 'me', name: 'appCard' }; }
使用
<app-card> <ng-template #header let-label let-item="otherDate"> <h1>Angular</h1> {{label}} (Test) and {{otherDate | json}} ({auth: 'me', name: 'appCard'}) </ng-template> </app-card>
更多编程相关知识,请访问:编程教学!!
The above is the detailed content of Let's talk about the method of content projection in angular. For more information, please follow other related articles on the PHP Chinese website!