Angular 一次在多个地方使用相同的 TemplateRef - 克隆 TemplateRef?

Jam*_*mes 5 angular angular6

我正在尝试构建一个多选组件,它可以为每个选择选项元素采用一个模板。它主要工作,模板是从选项组件中的 ng-content 中抓取的,并显示在“选择弹出窗口”中。

选项显示正常

尝试在选择组件中显示所选选项时遇到问题。似乎模板一次只能在一个地方显示,因此当在“选择”中显示所选选项时,它将从POPOVER中删除。

选项显示错误

有什么办法可以克隆 TemplateRef 组件吗?我实际上并不介意模板的上下文是否更新,因为我目前没有使用它的任何内容,只是模板。

为了清楚起见,包括下面的一些代码片段,我认为这没关系。

用途somepage.component.html

<my-select [(value)]="vals">
    <my-option *ngFor="let x of [1,2,3]" [value]="x">Option {{x}}</my-option>
</my-select>`
Run Code Online (Sandbox Code Playgroud)

我的选择.component.html

...
<ng-container [ngTemplateOutlet]="getSelectedOptionTemplate()"></ng-container>
...
Run Code Online (Sandbox Code Playgroud)

我的select.component.ts

getSelectedOptionTemplate(){
    // Some way to clone here could solve the issue?
    return this.getSelectedOption().template;
}
Run Code Online (Sandbox Code Playgroud)

my-select-overlay.component.html

...
<ng-container *ngFor="let opt of options;">
    <ng-container [ngTemplateOutlet]="getTemplate(opt)"></ng-container>
</ng-container>
...
Run Code Online (Sandbox Code Playgroud)

my-option.component.html

<ng-template>
    <ng-content></ng-content>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

my-option.component.ts

...
@ViewChild(TemplateRef)
template: TemplateRef<any>;
...
Run Code Online (Sandbox Code Playgroud)

and*_*tor -1

我在Github上找到了这个问题的解决方案。

TemplateRef当包装包含 的ng-template 组件时,似乎使用相同的方法可以工作ng-content

想象一下我们需要获得类似的东西:

<ng-template>
   <my-option>
      ... option content ...(<ng-content></ng-content>)
   </my-option>
</ng-template>`
Run Code Online (Sandbox Code Playgroud)

为了获得上面的结构,我们可以实现一个结构指令。来自文档:

Angular 将结构指令前面的星号转换为<ng-template>围绕宿主元素及其后代的星号。

结构指令的代码为:

@Directive({
  selector: "[appOptionTemplate]"
})
export class OptionTemplateDirective {
  @Input("appOptionTemplate")
  value: any;

  constructor(
    public templateRef: TemplateRef<any>
  ) {}
}
Run Code Online (Sandbox Code Playgroud)

(注意以下事项:

  • templateRef在构造函数中注入
  • 财产Input

填充选择选项时,我们将使用以下内容:

<app-select>
  <ng-container *ngFor="let x of [1,2,3]; let i=index;">
    <app-option *appOptionTemplate="x">
      Option {{x}}
    </app-option>
  </ng-container>
</app-select>
Run Code Online (Sandbox Code Playgroud)

现在,我们将使用结构指令来查询组件中的内容select

@ContentChildren(OptionTemplateDirective)
options: QueryList<OptionTemplateDirective>;
Run Code Online (Sandbox Code Playgroud)

为了显示该选项,我们将使用:

<ng-container *ngTemplateOutlet="option.templateRef"></ng-container>
Run Code Online (Sandbox Code Playgroud)

示例: https: //stackblitz.com/edit/angular-ivy-pues8t


GitHub主题:

https://github.com/angular/angular/issues/37995


有关结构指令的更多信息:

https://angular.io/guide/structural-directives