Angular 动态组件:@ViewChildren 为 QueryList 中的每个组件获取 ViewContainerRef
Angular Dynamic Components: @ViewChildren get ViewContainerRef for every component in QueryList
我正在构建一个带有动态选项卡的对话框,它可以接收要放置在选项卡主体中的组件。我很难使用@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 作为参考:
在我的项目中,我这样做是为了动态构建组件:
应用组件
<div *ngFor="let field of fields">
<app-dynamic-component [field]="field" ></app-dynamic-component>
</div>
应用动态-component.ts
@ViewChild(DynamicComponentDirective, {static: true}) adHost: DynamicComponentDirective;
...
loadComponent() {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(this.field.component);
const componentRef = <any>viewContainerRef.createComponent(componentFactory);
}
应用动态-component.html
<ng-template dynamic-component></ng-template>
最后是我的动态组件指令
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[dynamic-component]',
})
export class DynamicComponentDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
组件中的 @ViewChildren
无法正常工作,因为它缺少指示 ViewContainerRef
.
的 read
元数据 属性
组件
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);
}
)
}
}
p.s。可以使用生命周期钩子 AfterContentInit
or AfterViewInit
.
加载动态内容
我正在构建一个带有动态选项卡的对话框,它可以接收要放置在选项卡主体中的组件。我很难使用@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 作为参考:
在我的项目中,我这样做是为了动态构建组件:
应用组件
<div *ngFor="let field of fields">
<app-dynamic-component [field]="field" ></app-dynamic-component>
</div>
应用动态-component.ts
@ViewChild(DynamicComponentDirective, {static: true}) adHost: DynamicComponentDirective;
...
loadComponent() {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(this.field.component);
const componentRef = <any>viewContainerRef.createComponent(componentFactory);
}
应用动态-component.html
<ng-template dynamic-component></ng-template>
最后是我的动态组件指令
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[dynamic-component]',
})
export class DynamicComponentDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
组件中的 @ViewChildren
无法正常工作,因为它缺少指示 ViewContainerRef
.
read
元数据 属性
组件
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);
}
)
}
}
p.s。可以使用生命周期钩子 AfterContentInit
or AfterViewInit
.