替换已弃用的 Angular ComponentFactoryResolver、ComponentFactory

xpr*_*cts 38 angular

我使用以下代码在 HTMLElement 中创建动态组件:

\n
import {ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, Injector} from \'@angular/core\';\nimport {DynamicTableComponent} from \'../table/dynamic-table/dynamic-table.component\';\n\nexport class Table {\n    \n    private readonly el: Element;\n    private compRef!: ComponentRef<DynamicTableComponent>;\n\n    constructor(el: Element, private resolver: ComponentFactoryResolver, private injector: Injector, private appRef: ApplicationRef) {        \n        this.el = el;\n    }\n\n    public destruct(): void {\n        if (this.compRef !== null && this.compRef !== undefined) {\n            this.appRef.detachView(this.compRef.hostView);\n            // is done by this.compRef.destroy();\n            // this.compRef.instance.ngOnDestroy();\n            this.compRef.destroy();\n        }\n    }\n\n    public addTable(el: Element): void {\n        const compFactory: ComponentFactory<any> = this.resolver.resolveComponentFactory(DynamicTableComponent);\n        this.compRef = compFactory.create(this.injector, undefined, el);\n        this.appRef.attachView(this.compRef.hostView);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

该组件动态加载到 HTML 元素中并通过 AttachView 添加。然后该destruct()方法干净地移除该组件。它\xc2\xb4s 工作正常,但从 Angular 13 开始它\xc2\xb4s 已弃用。所以我没有\xc2\xb4t 有一个ViewContainerRef 并且我不\xc2\xb4t 真的知道如何在 > Angular 13 中正确地做到这一点!?

\n

你对我有什么建议吗?

\n

感谢和问候

\n

Eli*_*r00 59

Angular 13新的 API 中,无需将ComponentFactoryResolver注入到构造函数中,就像您在代码中所做的那样。

现在要动态创建组件,您必须使用ViewContainerRef.createComponent而不使用工厂。

所以,不要使用

const compFactory: ComponentFactory<any> = this.resolver.resolveComponentFactory(DynamicTableComponent);
Run Code Online (Sandbox Code Playgroud)

你可以做:

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

/**
your code logic
*/

constructor(private viewContainerRef: ViewContainerRef)

public addTable(): void {
   const component = this.viewContainerRef.createComponent(YourElement);

}
Run Code Online (Sandbox Code Playgroud)


Dyl*_*sky 16

花了几个小时后,我通过新的组件 API 更新找到了 Angular 13 Ivy 的正确解决方案:

首先,您需要创建一个指令,最好是在名为“directives”的子文件夹中,您可以手动执行或使用命令:

ng generate directive directives/DynamicChildLoader
Run Code Online (Sandbox Code Playgroud)

这将生成文件:

动态子加载器.directive.ts

您的代码将需要类似于:

ng generate directive directives/DynamicChildLoader
Run Code Online (Sandbox Code Playgroud)

现在在您的组件中转到 .HTML,您需要包含以下内容:

<ng-template dynamicChildLoader=""></ng-template>
Run Code Online (Sandbox Code Playgroud)

在你的 .TS 中:

import { Directive, ViewContainerRef } from '@angular/core';
    
@Directive({
  selector: '[dynamicChildLoader]',
})
export class DynamicChildLoaderDirective {
  constructor(public viewContainerRef: ViewContainerRef) {}
}
Run Code Online (Sandbox Code Playgroud)

不要忘记在您的 app.module.ts 或您用来在声明部分包含 DynamicChildLoaderDirective 的模块中

<ng-template dynamicChildLoader=""></ng-template>
Run Code Online (Sandbox Code Playgroud)

  • 但是 - YourDynamicChildComponent 是固定的,此设置只会创建一个单一类型 - 即动态的 YourDynamicChildComponent。如果你想创建几种不同的类型怎么办?基于枚举/字符串/类型?YourDynamicChild1、YourDynamicChild2、YourDynamicChild3 等... (3认同)