我首先有一个看起来像这样的父/子组件
家长
<child-comp>
<div firstContent>This is my first content</div>
<div secondContent>This is my second content</div>
</child-comp>
孩子
<div redColourDirective>
<div>This is the template with directive applied</div>
<ng-content select="[firstContent]"></ng-content>
<ng-content select="[secondContent]"></ng-content>
</div>
...然后我希望指令 redColourDirective 是有条件的,因此模板变成了这样(主要是因为我不能有条件指令)
<ng-container *ngTemplateOutlet="withDirective() ? tmp1 : tmp2"> </ng-container>
<ng-template #tmp1>
<div redColourDirective>
<div>This is the template with directive applied</div>
<ng-content select="[firstContent]"></ng-content>
<ng-content select="[secondContent]"></ng-content>
</div>
</ng-template>
<ng-template #tmp2>
<div>
<div>This is the template WITHOUT directive applied</div>
<ng-content select="[firstContent]"></ng-content>
<ng-content select="[secondContent]"></ng-content>
</div>
</ng-template>
...其中 withDirective() 是作为输入的信号。现在,当 withDirective 从父组件设置为 true 时,firstContent、secondContent 会投影到子组件中,但当它为 false 时则不会。我在这里做错了什么?
//works, ng-content visible
<child-comp [withDirective]="true">
<div firstContent>This is my first content</div>
<div secondContent>This is my second content</div>
</child-comp>
//fails, no ng-content visible
<child-comp [withDirective]="false">
<div firstContent>This is my first content</div>
<div secondContent>This is my second content</div>
</child-comp>
我尝试过的:Stackblitz 演示
在条件/循环中使用
ng-content
会引起皱眉 - 文档参考
我猜代码的问题在于,
ng-content
仅在动态渲染 ng-content 时才捕获两个插槽。
您可以尝试将指令添加到两个条件中,但它仍然不会渲染。
更好的解决方案是去掉
ng-content
并用 *ngTemplateOutlet
代替,它可以渲染模板。
<ng-container *ngTemplateOutlet="withDirective() ? tmp1 : tmp2"> </ng-container>
<ng-template #tmp1>
<div redColourDirective>
<div>This is the template with directive applied</div>
<ng-container *ngTemplateOutlet="firstContent()"></ng-container>
<ng-container *ngTemplateOutlet="secondContent()"></ng-container>
</div>
</ng-template>
<ng-template #tmp2>
<div>
<div>This is the template WITHOUT directive applied</div>
<ng-container *ngTemplateOutlet="firstContent()"></ng-container>
<ng-container *ngTemplateOutlet="secondContent()"></ng-container>
</div>
</ng-template>
然后,我们不传入 div,而是传入
ng-template
,其中将包含您想要动态渲染的内容。
<child-comp [withDirective]="false">
<ng-template #firstContent>This is my first content</ng-template>
<ng-template #secondContent>This is my second content</ng-template>
</child-comp>
<hr />
<child-comp [withDirective]="true">
<ng-template #firstContent>This is my first content</ng-template>
<ng-template #secondContent>This is my second content</ng-template>
</child-comp>
最后,我们使用信号
contentChild
来访问此模板并使其可用于子 html。
import { Component, input, output, signal, contentChild } from '@angular/core';
import { Action } from './models';
import { NgTemplateOutlet } from '@angular/common';
import { RedColourDirective } from './colour-directive';
@Component({
selector: 'child-comp',
templateUrl: './child.component.html',
standalone: true,
imports: [NgTemplateOutlet, RedColourDirective],
})
export class ChildComponent {
firstContent: any = contentChild('firstContent');
secondContent: any = contentChild('firstContent');
withDirective = input<boolean>();
constructor() {}
}