找不到未定义的组件工厂。您是否将其添加到@ NgModule.entryComponents

时间:2018-08-23 16:15:59

标签: angular angular-cli-v6 angular-library

我创建了一个Angular 6组件库。 该库基于PrimeNG组件。 库中的组件之一是表组件(基于PrimeNG表)

要允许库的用户在我在库中创建的名为“ VarintComponent”的组件的表单元格中添加动态模板,该组件有两个输入:

1)GuestComponent:字符串

2)GuestComponentData:任意

该表的用户可以声明一列包含VariantComponent,并将组件的名称传递给GuestComponent Input。 在运行时,VariantComponent使用componentFactoryResolverviewContainerRef动态创建和加载组件。

import { Component, OnInit, Input, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { Type } from '@angular/core';
import { VariantComponentDirective } from './variant-component.directive';

@Component({
  selector: 'o-variant',
  template: `
        <ng-template variantComponent></ng-template>
        `
})
export class VariantComponent implements OnInit {
  @Input() GuestComponent: String;
  @Input() GeustComponentData: any;

  @ViewChild(VariantComponentDirective) variantHost: VariantComponentDirective;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {
    this.loadComponent();
  }

  loadComponent() {
    const viewContainerRef = this.variantHost.viewContainerRef;
    viewContainerRef.clear();

    const factories = Array.from(this.componentFactoryResolver['_factories'].keys());
    const factoryClass = <Type<any>>factories.find((x: any) => x.name === (this.GuestComponent));
    const factory = this.componentFactoryResolver.resolveComponentFactory(factoryClass);
    const compRef = viewContainerRef.createComponent(factory);

    (<any>compRef.instance).data = this.GeustComponentData;
  }

}

来宾组件需要实现一个简单的接口,以托管在VariantComponent中。

还将来宾组件声明为其模块的“ entryComponents”。

在其他项目中使用表格时,我可以看到所有工作正常,并且Gust组件已正确托管在VarintComponent中,并显示在表格中。

问题是,在构建生产包(使用ng build --prod)时,我得到了:

main.11fb9744a37aae5b78f8.js:1 ERROR Error: No component factory found for undefined. Did you add it to @NgModule.entryComponents?

无论访客组件位于库还是客户端项目中,我都会收到此错误。

如果我使用ng build --build-optimizer=false

进行构建,代码将运行良好

1 个答案:

答案 0 :(得分:0)

发现了问题。 问题在于以下行:

const factoryClass = <Type<any>>factories.find((x: any) => x.name === (this.GuestComponent));

使用--prod包装时,包装会被丑陋,并且类名称已更改,因此我们无法按名称进行比较。 因此,我们需要通过引用传递组件。 以下代码效果很好:

import { Component, OnInit, Input, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { VariantComponentDirective } from './variant-component.directive';


@Component({
  selector: 'o-variant',
  template: `
        <ng-template variantComponent></ng-template>
        `
})
export class VariantComponent implements OnInit {
  @Input() GuestComponent: any;
  @Input() GeustComponentData: any;

  @ViewChild(VariantComponentDirective) variantHost: VariantComponentDirective;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {
    this.loadComponent();
  }

  loadComponent() {
    const viewContainerRef = this.variantHost.viewContainerRef;
    viewContainerRef.clear();
    const factory = this.componentFactoryResolver.resolveComponentFactory(this.GuestComponent);
    const compRef = viewContainerRef.createComponent(factory);
    (<any>compRef.instance).data = this.GeustComponentData;
  }

}