【问题标题】:How can I get an ng-content select filter to work with projected template content?如何让 ng-content 选择过滤器与投影模板内容一起使用?
【发布时间】:2020-01-09 05:39:31
【问题描述】:

我有一个用于呈现列表的List 组件。 (嗯,我没有,但我试图将我的问题提炼成一个易于理解的点头示例)。

List 组件的模板具有一个或多个 ListItem 组件,这些组件允许定义列表项,如下所示:

<app-list>
  <app-list-item text='foo'></app-list-item>
  <app-list-item text='bar'></app-list-item>
</app-list>

...应该呈现为:

  • 酒吧

我也有(假设)一个使用List 组件的Reminder 组件。 Reminder 组件有一个deadline 属性,在这个截止日期之前要做的事情列表在组件的模板中定义,使用我们之前看到的一个或多个ListItem 组件:

<app-reminder deadline='Today'>
  <app-list-item text='foo'></app-list-item>
  <app-list-item text='bar'></app-list-item>
</app-reminder>

这应该呈现为:

记得在今天之前做到以下几点:

  • 酒吧

List 组件非常简单:

@Component({
  selector: 'app-list',
  template: `
    <ul>
      <ng-content></ng-content>
    </ul>
  `
})
export class ListComponent{
  @ContentChildren(ListItemComponent) public readonly items: QueryList<ListItemComponent>;
}

ListItem 组件更简单:

@Component({
  selector: 'app-list-item',
  template: '<li>{{text}}</li>'
})
export class ListItemComponent {
  @Input() public text;
}

最后,Reminder 组件也很简单:

@Component({
  selector: 'app-reminder',
  template: `
    <h2>Remeber to do the following by {{deadline}}</h2>
    <app-list>
      <ng-content></ng-content>
    </app-list>
  `
})
export class ReminderComponent {
  @Input() public deadline: string;
}

将这些组件与上面显示的模板 sn-ps 一起使用可以正常工作。您可以在 this StackBlitz 中看到这一点。

现在进入问题的重点。 List 组件和Reminder 组件都使用&lt;ng-content&gt;。在这两种情况下,我们都不想将 所有 内容投影到列表中 - 只是 &lt;app-list-item&gt; 元素。

如果我像这样更改Reminder 组件模板中的&lt;ng-content&gt; 标记:

<ng-content select='app-list-item'></ng-content>

...那么组件仍然可以工作,并排除其模板中的任何其他内容,这正是我们想要的。

如果我对 List 组件的模板中的 &lt;ng-content&gt; 标记进行相同的更改,这也适用于像这样的简单模板:

<app-list>
  <app-list-item text='foo'></app-list-item>
  <app-list-item text='bar'></app-list-item>
  <h1>EXCLUDE ME</h1>
</app-list>

但是,最后的更改(在List 组件的模板中添加select 过滤器到&lt;ng-content&gt; 元素)使Reminder 组件停止工作。提醒中不呈现任何列表项。

我想这可能是因为Reminder 组件的模板渲染的List 组件看到的是渲染的 内容(&lt;li&gt; 标签)而不是模板 em> 内容(&lt;app-list-item&gt; 标签)。

似乎我在这里有一个不愉快的选择 - 我可以限制将由 List 组件呈现的内容类型(在这种情况下,可能会包含任何旧垃圾) ,或在创建其他组件时失去使用List 组件的能力。

或者我错过了什么?有没有其他方法可以做到这一点?

【问题讨论】:

  • 我查看了 StackBlitz,并且可以按照逻辑向下直到“但是,添加...”:-) 任何机会您都可以在出现问题时更新 StackBlitz
  • 您可以像这样在ListComponent 中定义选择过滤器,以考虑嵌套内容投影:&lt;ng-content select='app-list-item,ng-content'&gt;。它有效,但我真的不确定这样做是否是个好主意。
  • @Drenai:分叉的 StackBlitz 显示了当我在 List 组件的模板中向 &lt;ng-content&gt; 添加过滤器时会发生什么:stackblitz.com/edit/angular-mkxq2b

标签: angular angular-components


【解决方案1】:

我设法通过使用ngProjectAs 解决了这个问题。

reminder.component.ts

@Component({
  selector: 'app-reminder',
  template: `
    <h2>Remeber to do the following by {{deadline}}</h2>
    <app-list>
      <ng-container ngProjectAs="'app-list-item'">
        <ng-content select='app-list-item'></ng-content>
      </ng-container>
    </app-list>
  `
})
export class ReminderComponent {
  @Input() public deadline: string;
}

Here is the StackBlitz demo.

【讨论】:

  • 太棒了——这正是我想要的。谢谢!
  • 我以前从未见过ngProjectAs 被使用过——也感谢您发布文章链接
  • @Andrei Gatej - 请您解释一下 ngProjectAs 是如何解决这个问题的 - 我遇到了这个问题,但是如何使用 ngProjectAs 仍然没有得到解决。
  • @shrey 这里是另一个SO answer,它描述了ngProjectAs。自 2019 年以来情况可能发生了变化,所以我不确定它现在是否会保持不变。
  • @AndreiGătej - 我想说的是,您能否通过使用此代码将 包含在提醒组件中来解释一下 它如何开始完美呈现?我没有得到,添加 ngProjectAs 后如何完美地工作。
猜你喜欢
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2019-01-17
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
相关资源
最近更新 更多