简体   繁体   English

Angular 11 DI 用于动态编译组件

[英]Angular 11 DI for dynamically compiled components

Using JitCompilerFactory and compiling components at runtime works (for example see here: https://stackoverflow.com/a/67122569/15816951 ) but injecting into dynamic component does not:使用 JitCompilerFactory 并在运行时编译组件有效(例如,请参见此处: https://stackoverflow.com/a/67122569/15816951 )但注入动态组件不会:

// (1) define Component metadata
const metadata = new Component({
  selector: "dynamic-selector",
  template: "This is template: {{text}}"    // <---- Interpolation: works
});

// (2) define Component class and decorate
const compClass = class DynamicComponent {
   text: string = 'from';                   // <---- Interpolation: works
   constructor(public s: Service1) { }      // <---- Trying to inject a service: FAILS
};
const decoratedComp = Component(metadata)(compClass);

// (3) define Module class and decorate
const decoratedModule = NgModule({
   imports: [...],
   declarations: [decoratedCmp]
})(class DynamicModule { }) 

// (4 )compile Module and grab the Component Factory
const module  = compiler.compileModuleAndAllComponentsAsync(decoratedModule);
const factory = module.componentFactories.find(x => x.componentType === decoratedCmp);

// (5) render the component using Component Factory
someViewContainerRef.createComponent(factory);

Without the DI in component class constructor (#2 above) all is fine but trying to inject causes:如果没有组件 class 构造函数(上面的#2)中的 DI,一切都很好,但尝试注入原因:

core.js:6210 ERROR Error: Uncaught (in promise): Error: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid. core.js:6210 错误错误:未捕获(承诺中):错误:此构造函数与 Angular 依赖注入不兼容,因为它在参数列表索引 0 处的依赖无效。
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.如果依赖类型是像字符串这样的原语,或者如果此 class 的祖先缺少 Angular 装饰器,则会发生这种情况。
Please check that 1) the type for the parameter at index 0 is correct and 2) the correct Angular decorators are defined for this class and its ancestors.请检查 1) 索引 0 处的参数类型是否正确,以及 2) 为此 class 及其祖先定义了正确的 Angular 装饰器。 Error: This constructor is not compatible with Angular Dependency Injection because its dependency at index 0 of the parameter list is invalid.错误:此构造函数与 Angular 依赖注入不兼容,因为它在参数列表索引 0 处的依赖无效。 This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.如果依赖类型是像字符串这样的原语,或者如果此 class 的祖先缺少 Angular 装饰器,则会发生这种情况。

I tried to add core-js/es/reflect and reflect-metadata in polyfills.ts based on this answer from Angular team for Angular 9: https://github.com/angular/angular/issues/35908 (DI error when using JIT from an AoT-compiled Ivy project).我尝试根据 Angular 团队对 Angular 9: Z5E056C500A1C4B6A7110B508/angular /angular/angular/issues/3Z 的回答在polyfills.ts中添加core-js/es/reflectreflect-metadata来自 AoT 编译的 Ivy 项目的 JIT)。

What should I do to make DI work for dynamic components in Angular 11?在 Angular 11 中,我应该怎么做才能使 DI 对动态组件起作用?

Answering my question in case someone is after same thing.回答我的问题,以防有人追求同样的事情。 Thanks to those who replied on Angular issue tracker: https://github.com/angular/angular/issues/41933感谢那些在 Angular 问题跟踪器上回复的人: https://github.com/angular/angular/issues/41933

DI fails because TS compilation is way before at point where we create component class at runtime and Angular has no metadata information available for the constructor. DI 失败是因为 TS 编译早于我们在运行时创建组件 class 并且 Angular 没有可用于构造函数的元数据信息。 Sou you can either:你可以:

Provide injection metadata manually like:手动提供注入元数据,例如:

(cmpClass as any).ctorParameters = () => [ {type: Service1 }];

Or add a decorator and call it in an IIFE like:或者添加一个装饰器并在 IIFE 中调用它,例如:

export function Annotate() {
   return klass => klass;
}

const cmpClass = (() => {
   @Annotate()
   class DynamicComponent {
     text: string = "Text";

     constructor(public s: Service1) {
       console.log(s);
     }

     handle() {
       this.text = "Event handler works!";
     }
   }
   return DynamicComponent;
 })();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM