子组件中多个相似的命名条件ng-内容未投影

问题描述 投票:0回答:1

我首先有一个看起来像这样的父/子组件

家长

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

angular signals ng-template angular-signals angular-content-projection
1个回答
0
投票

在条件/循环中使用

ng-content
会引起皱眉 - 文档参考

我猜代码的问题在于,

ng-content
仅在动态渲染 ng-content 时才捕获两个插槽。

您可以尝试将指令添加到两个条件中,但它仍然不会渲染。


更好的解决方案是去掉

ng-content
并用
*ngTemplateOutlet
代替,它可以渲染模板。

child.component.html

<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
,其中将包含您想要动态渲染的内容。

app.component.html

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

child.component.ts

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() {}
}

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.