如何获得ng-content选择过滤器以处理投影的模板内容?

时间:2019-09-06 10:34:22

标签: angular angular-components

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

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

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

...应呈现为:

  
      
  • foo
  •   
  • 酒吧
  •   

我也有一个Reminder组件,它使用List组件。 Reminder组件具有deadline属性,并且使用我们之前看到的一个或多个ListItem组件,在该截止日期之前要做的事情清单是在该组件的模板中定义的:< / p>

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

这应该呈现为:

  

请记住在今天之前执行以下操作:

     
      
  • foo
  •   
  • 酒吧
  •   

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

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

现在是问题的重点。 List组件和Reminder组件都使用<ng-content>。在这两种情况下,我们实际上都不希望将所有内容投影到列表中,而只是将<app-list-item>元素投影到列表中。

如果我像这样更改<ng-content>组件模板中的Reminder标签:

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

...然后,该组件仍然可以工作,并且在模板中排除了我们想要的任何其他内容。

如果我对<ng-content>组件的模板中的List标签进行了相同的更改,那么这也适用于像这样的简单模板:

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

但是,最后一次更改(向select组件模板中的<ng-content>元素添加List过滤器)停止了Reminder组件从工作。提醒中没有呈现任何列表项。

我想这可能是因为List组件的模板所呈现的Reminder组件看到的是 rendered 内容(<li>标签),而不是 template 内容(<app-list-item>标签)。

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

还是我错过了什么?还有另一种方法吗?

1 个答案:

答案 0 :(得分:2)

我设法使用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