如何以编程方式实例化组件并将其插入模板中的指定位置?
堆栈闪电战:https://stackblitz.com/edit/angular-do71xk
import {Component, ComponentFactoryResolver, TemplateRef, ViewChild, ViewContainerRef, Type} from "@angular/core";
export interface PaneOptions {
component: Type<any>;
params?: any;
}
@Component({
selector: 'app-manager',
template: `
<ng-template #paneContainer></ng-template> <!-- probably redundant -->
<!-- window template -->
<ng-template #paneTemplate>
<div style="background: red">
<h3>Window header</h3>
<ng-template #paneBody></ng-template> <!-- or another ng-template -->
</div>
</ng-template>
`
})
export class ManagerComponent {
@ViewChild('paneContainer', {read: ViewContainerRef}) paneContainer: ViewContainerRef;
@ViewChild('paneTemplate', {read: ViewContainerRef}) paneTemplateRef: ViewContainerRef;
@ViewChild('paneTemplate', {read: TemplateRef}) paneTemplate: TemplateRef<any>;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
addPane(options: PaneOptions) {
// create embedded view of pane template
const embeddedView = this.paneContainer.createEmbeddedView(this.paneTemplate);
// resolve component and insert it into pane container
// instead, we need to clone #paneTemplate and insert component within <ng-content>
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(options.component);
const component = this.paneTemplateRef.createComponent(componentFactory);
Object.assign(component.instance, options.params);
}
}
当我尝试在内部 ng 模板中实例化组件时,这是不同的方法。
import {Component, ComponentFactoryResolver, TemplateRef, ViewChild, ViewContainerRef, Type} from "@angular/core";
export interface PaneOptions {
component: Type<any>;
params?: any;
}
@Component({
selector: 'app-manager',
template: `
<ng-template #paneContainer></ng-template>
<!-- pane template -->
<ng-template #paneTemplate>
<div style="background: red">
<h3>Below within red area should be the inner component</h3>
<ng-template #inner></ng-template>
</div>
</ng-template>
`
})
export class ManagerComponent {
@ViewChild('paneContainer', {read: ViewContainerRef}) paneContainer: ViewContainerRef;
@ViewChild('inner', {read: ViewContainerRef}) innerTemplateRef: ViewContainerRef;
@ViewChild('paneTemplate', {read: TemplateRef}) paneTemplate: TemplateRef<any>;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
addPane(options: PaneOptions) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(options.component);
const component = this.innerTemplateRef.createComponent(componentFactory);
Object.assign(component.instance, options.params);
// create embedded view of pane template
const embeddedView = this.paneContainer.createEmbeddedView(this.paneTemplate);
}
}
堆叠闪电战:https://stackblitz.com/edit/angular-dzx7vz
但是,我收到错误:
错误:无法读取未定义的属性"创建组件">
我正在使用Angular编写窗口管理器。是否可以将组件注入窗口模板的指定位置,然后将窗口插入主容器?我想保留对每个窗口的引用,以便能够进一步删除它。
您必须为此进行三个主要更改。
-
需要编写一个主机指令来托管您的动态 此处解释的组件 - https://angular.io/guide/dynamic-component-loader
-
使用
@ViewChild(HostDirective, {static: false}) hostDirective;
-
将组件加载延迟到下一次更改检测 - 使用
setTimeout
你可以参考这个堆栈闪电战 https://stackblitz.com/edit/angular-kbjr75