如何在Angular 2中动态渲染模板

How to render templates dynamically in Angular 2?

本文关键字:动态 Angular      更新时间:2023-09-26

我试图在视图中动态地选择模板,只需使用Angular 2中传统的"#"字符来引用它们。在我的项目中,我处理错误并将它们显示给用户,我有一个对话框组件,它的内容应该是基于动态注入的html,所以这就是为什么我使用模板。

我读了一些文章,其中显示了如何做到这一点,当我已经知道模板引用的名称,在我的情况下,我不知道引用的名称,我得到运行时的名称。我特别遵循了这个指南:https://www.bennadel.com/blog/3101-experimenting-with-dynamic-template-rendering-in-angular-2-rc-1.htm

所以目前我的dialog组件有以下视图:

<template #err_1 let-property1="p1" let-property2="p2">
property1: {{p1}}
property2: {{p2}}
</template>
<template #err_2 let-property1="p1" let-property2="p2">
<p *ngIf="p1">{{p1}}</p>
property2: {{p2}}
</template>
<!--The code for the template directive i took from the guide in the link above-->
<tem [render]="templateRef"
     [context]="context">
</tem>

在我的对话框。我有以下代码:

@Component({
  selector: 'error-dialog',
  queries: {
    templateRef: new ViewChild("err_1")
  },
  templateUrl: './dialog.html'
})
...

"TemplateRendererDirective"指令的源代码是我从上面的链接中找到的。注意什么让我困惑:templateRef基本上得到一个对象:"ViewChild"即使指令最终得到templateRef实例,这是怎么可能的?

所以只有当我知道我想要渲染的错误模板时,例如:"err_1",我只是在对话框中事先引用它。Ts,但事实并非如此,我想动态地告诉我想渲染"err_1","err_2"等。并给出上下文(它是用数据填充模板的对象-在示例中也是动态的p1, p2)

这可能吗?

正如我在评论中提到的,你可以尝试使用@ViewChildren来完成它的工作。但我使用额外的指令TemplateNameDirective来操作模板的name

是这样的:

@Directive({
  'selector': 'template[name]'
})
export class TemplateNameDirective {
  @Input() name: string;
  constructor(public templateRef: TemplateRef<any>) {}
}
@Component({
  selector: 'error-dialog',
  template: `
    <template name="err_1" let-item>
      property1: {{item.p1}}
      property2: {{item.p2}}
    </template>
    <template name="err_2" let-item>
      <p *ngIf="item.p1">{{item.p1}}</p>
      property2: {{item.p2}}
    </template>
    <!-- 
       I use ngTemplateOutlet directive 
       https://angular.io/docs/ts/latest/api/common/index/NgTemplateOutlet-directive.html 
    -->
    <template [ngTemplateOutlet]="templateRef" [ngOutletContext]="{ $implicit: context }">
    </template>
  `
})
export class ErrorDialogComponent {
  @ViewChildren(TemplateNameDirective) children: QueryList<TemplateNameDirective>;
  templateRef: TemplateRef<any>;
  context: any;
  public setContent(errTemplateName, context) {
    this.templateRef = this.children.toArray()
      .find(x => x.name === errTemplateName).templateRef; 
    this.context = context;
  }
}

父视图:

<error-dialog #dialogRef></error-dialog>
<button (click)="dialogRef.setContent('err_1', { p1: 'test'})">Test err_1</button>
<button (click)="dialogRef.setContent('err_2', { p2: 'test2'})">Test err_2</button>
<<p> 恰好例子/strong>

注意:我正在传递具有$implicit属性的ngOutletContext类对象。

在上下文对象中使用隐式键$将把它的值设置为违约。

它的工作原理如下:

[ngOutletContext]="{ $implicit: row }"  ==> <template let-row>
[ngOutletContext]="{ item: row }"       ==> <template let-row="item">