在ngFor中使用ngTemplate加载动态组件

时间:2018-02-21 23:23:21

标签: angular angular-material angular-directive

我正在尝试设置这样的动态扩展面板:

<mat-accordion>
  <mat-expansion-panel *ngFor="let category of categories">
    <mat-expansion-panel-header>
      <mat-panel-title>
        {{category.name}}
      </mat-panel-title>
    </mat-expansion-panel-header>
    <ng-template #category>
      <a>Test</a>
    </ng-template>
    <mat-action-row>
      <button mat-button color="primary" (click)="nextStep()">Next</button>
    </mat-action-row>
  </mat-expansion-panel>
</mat-accordion>

在我的组件中,我试图访问每个模板,如下所示:

@ViewChildren('category') components: QueryList<CategoryDirective>;

ngAfterViewInit() {
    const viewContainerRef = this.adHost;
    if (!_.isUndefined(this.categories) && !_.isUndefined(this.components)) {
      this.components.changes.subscribe(() => {
        this.components.toArray().forEach(el => {
            console.log('ngAfterViewInit', el);
        });
      });
    }
  }

对于每个类别,我都有一个我想在ngTemplate中加载的组件属性。

enter image description here

我该怎么做?

1 个答案:

答案 0 :(得分:0)

由于@ViewChild因多个&#34;类别&#34;而无法正常工作指令。您可以通过为每个项目创建单独的组件来解决此问题。

<mat-accordion>
  <ng-template ngFor let-category [ngForOf]="categories" let-i="index">
    <expansion-panel [title]="category.name" [component]="category.component" [isSelected]="category.isSelected" [index]="i"></expansion-panel>
  </ng-template>
</mat-accordion>

HTML:

<mat-expansion-panel [disabled]="!isSelected">
  <mat-expansion-panel-header>
    <mat-panel-title>
      {{title}}
    </mat-panel-title>
  </mat-expansion-panel-header>
  <ng-template category></ng-template>
  <mat-action-row>
    <button mat-button color="primary" (click)="nextStep()">Next</button>
  </mat-action-row>
</mat-expansion-panel>

并在扩展面板组件中添加以下内容。

TS:

@ViewChild(CategoryDirective) categoryDirective: CategoryDirective;

@Input() component: any;

之后,您可以动态添加组件:

ngAfterViewInit(): void {
    if (!_.isUndefined(this.component)) {
      const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
      const viewContainerRef = this.categoryDirective.viewContainerRef;
      console.log(viewContainerRef);
      if (!_.isUndefined(viewContainerRef)) {
        viewContainerRef.clear();

        const componentRef = viewContainerRef.createComponent(componentFactory);
        // (<CategoryComponent>componentRef.instance).data = adItem.data;
      }
    }
  }