【问题标题】:Angular Dynamic Components: @ViewChildren get ViewContainerRef for every component in QueryListAngular 动态组件:@ViewChildren 为 QueryList 中的每个组件获取 ViewContainerRef
【发布时间】:2020-01-03 09:18:09
【问题描述】:

我正在构建一个带有动态选项卡的对话框,该对话框可以接收要放置在选项卡正文中的组件。我很难使用@ViewChildren 创建多个动态组件。我过去很容易用单个组件和@ViewChild 成功地做到了这一点。

这是我的模板:

<mat-tab *ngFor="let tab of tabs" [label]="tab.label">
     <ng-template #comp></ng-template>
</mat-tab>

这是我的组件逻辑:

@ViewChildren("comp") dynComponents: QueryList<any>;


public ngAfterContentInit() {
  this.tabs.forEach(tab => {
     const factory = this._resolver.resolveComponentFactory(tab.component);
     console.log(this.dynComponents); // Returns undefined.

     // this.componentRef = this.vcRef.createComponent(factory);
  });
}

即使在模板中硬编码组件时,我的 dynComponents 也是未定义的。我似乎需要从这个 dynComponents QueryList 中获取 ViewContainerRef,但我不确定为什么它根本没有填充。我用这个帖子作为参考:Post

【问题讨论】:

  • 尝试使用 ngAfterViewInit。无论如何-我必须检查一下-我认为如果在 AfterViewInit 发生时您的模板不在视图中,您需要订阅this.dynComponents.changes.subscribe(res=&gt;{..here you has your dnyComponent..}

标签: angular angular-dynamic-components


【解决方案1】:

组件中的@ViewChildren 不起作用,因为它缺少指示ViewContainerRefread 元数据属性。

组件

import {
  AfterContentInit, Component, ComponentFactoryResolver, QueryList, Type, ViewChildren, ViewContainerRef
} from '@angular/core';


@Component({
  selector: 'dynamic-dialog',
  templateUrl: './dynamic-dialog.component.html',
  styleUrls: ['./dynamic-dialog.component.scss']
})
export class DynamicDialogComponent implements AfterContentInit {
  @ViewChildren('comp', { read: ViewContainerRef })
  public dynComponents: QueryList<ViewContainerRef>;

  public tabs = [];

  constructor(private _resolver: ComponentFactoryResolver) {}

  ngAfterContentInit() {
    this.dynComponents.map(
      (vcr: ViewContainerRef, index: number) => {
        const factory = this._resolver.resolveComponentFactory(
          this.tabs[index].component);
        vcr.createComponent(factory);
      }
    )
  }
}

附言可以使用生命周期挂钩 AfterContentInitAfterViewInit 加载动态内容。

【讨论】:

  • 这按预期工作。不错的解决方案!任何将来查看此帖子的人,请确保在创建它们时存储您的 comp refs 并在 ngOnDestroy 上销毁它们!
【解决方案2】:

在我的项目中,我这样做是为了动态构建组件:

应用组件

   <div *ngFor="let field of fields">
        <app-dynamic-component [field]="field" ></app-dynamic-component>
    </div>

应用动态组件.ts

  @ViewChild(DynamicComponentDirective, {static: true}) adHost: DynamicComponentDirective;

...
loadComponent() {
    const componentFactory = 
        this.componentFactoryResolver.resolveComponentFactory(this.field.component);

    const componentRef = <any>viewContainerRef.createComponent(componentFactory);
}

应用动态组件.html

<ng-template dynamic-component></ng-template>

最后是我的动态组件指令

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[dynamic-component]',
})
export class DynamicComponentDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}

【讨论】:

    猜你喜欢
    • 2018-12-01
    • 2017-10-27
    • 2016-11-11
    • 2017-06-27
    • 2020-12-08
    • 2019-09-08
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多