如何在 <ng-template> 的指定位置以编程方式注入组件?
How to inject component programatically at specified place of <ng-template>?
如何以编程方式实例化组件并将其插入到模板中的指定位置?
Stackblitz: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-template 中实例化组件时,这是不同的方法。
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);
}
}
Stackblitz:https://stackblitz.com/edit/angular-dzx7vz
但是,我得到错误:
Error: Cannot read property 'createComponent' of undefined
我正在使用 Angular 编写 window 管理器。是否可以将组件注入 window 模板的指定位置,然后将 window 插入主容器?我想保留对每个 window 的引用,以便能够进一步删除它。
您必须为此进行三项主要更改。
需要编写一个主机指令来托管您的动态
此处解释的组件 - https://angular.io/guide/dynamic-component-loader
使用
抓住你的主机指令
@ViewChild(HostDirective, {static: false}) hostDirective;
将组件加载延迟到下一次更改检测 - 使用 setTimeout
你可以参考这个 stackBlitz https://stackblitz.com/edit/angular-kbjr75
如何以编程方式实例化组件并将其插入到模板中的指定位置?
Stackblitz: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-template 中实例化组件时,这是不同的方法。
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);
}
}
Stackblitz:https://stackblitz.com/edit/angular-dzx7vz
但是,我得到错误:
Error: Cannot read property 'createComponent' of undefined
我正在使用 Angular 编写 window 管理器。是否可以将组件注入 window 模板的指定位置,然后将 window 插入主容器?我想保留对每个 window 的引用,以便能够进一步删除它。
您必须为此进行三项主要更改。
需要编写一个主机指令来托管您的动态 此处解释的组件 - https://angular.io/guide/dynamic-component-loader
使用
抓住你的主机指令@ViewChild(HostDirective, {static: false}) hostDirective;
将组件加载延迟到下一次更改检测 - 使用
setTimeout
你可以参考这个 stackBlitz https://stackblitz.com/edit/angular-kbjr75