首页 文章

Angular2 RC 5.找不到动态加载组件的组件工厂

提问于
浏览
39

我正在尝试将我的动态组件加载程序从RC4更新到RC5,因为不推荐使用ComponentResolver . 我已将加载程序更新为以下内容

@Component({
    selector: 'component-dispatcher',
    template: `<div #container></div>` // Define the template here because of its brevity
})
export class ComponentDispatcherComponent implements OnInit, OnDestroy {
    @Input() component:any; // Some dynamic component to render
    @Input() options:any;   // Component configuration, optional
    @Input() data:any;      // Data to render within the component

    // Inject the dynamic component onto the DOM
    @ViewChild("container", {read: ViewContainerRef}) container:ViewContainerRef;

    private componentReference:ComponentRef<any>;

    constructor(private resolver:ComponentFactoryResolver) {
    }

    ngOnInit() {
        // Create our component now we're initialised
        let componentFactory = this.resolver.resolveComponentFactory(this.component);
        this.componentReference = this.container.createComponent(componentFactory);
        this.componentReference.instance.data = this.data;
        this.componentReference.instance.options = this.options;
    }

    ngOnDestroy() {
        // If we have a component, make sure we destroy it when we lose our owner
        if (this.componentReference) {
            this.componentReference.destroy();
        }
    }
}

并尝试将以下组件动态加载到DOM中

@Component({
    selector: 'text-cell',
    pipes: [IterableObjectPipe],
    templateUrl: './text-cell.component.html',
    styles: ['.fieldName { font-weight: bold; }']
})
export class TextCellComponent implements OnInit {
    // Data to render within the component
    @Input() data: any;
    @Input() record: any;

    // Configuration of what data to display
    @Input() options: {
        excludeFieldNames: boolean,
        translation: string
    };

    constructor() {
    }

    ngOnInit() {
        setTimeout(() => {
            //console.log('***************************** ngOnInit...textCell ***********************');
            this.options.translation = '' + (_.get(this.options, 'translation') || 'fields');
        });
    }
}

然而,当我使用我的TextCellComponent或应用程序中的任何其他组件执行此操作时,我收到以下错误

ORIGINAL EXCEPTION: No component factory found for TextCellComponent
ORIGINAL STACKTRACE:
Error: No component factory found for TextCellComponent
at NoComponentFactoryError.BaseException [as constructor]      
(webpack:///./~/@angular/core/src/facade/exceptions.js?:27:23)
at new NoComponentFactoryError

我已经完成了步骤

https://angular.io/docs/ts/latest/cookbook/rc4-to-rc5.html

但我似乎错过了一些东西 . 我已经尝试将组件添加到bootstrapping并在全局定义它们而没有运气 . 任何的意见都将会有帮助 .

EDIT

添加模块定义

@NgModule({
    imports: [
        BrowserModule, 
        HttpModule, 
        FormsModule, 
        ReactiveFormsModule, 
        ...MATERIAL_MODULES
    ],
    declarations: [
        ...APPLICATION_PIPES, 
        ...APPLICATION_COMPONENTS, 
        ...APPLICATION_DIRECTIVES, 
        CygnusComponent,
        // Component declarations
        // TODO: refactor to appropriate modules
        ...
        ComponentDispatcherComponent,
        TextCellComponent,
        ...
    ],
    bootstrap: [
        ApplicationComponent
    ],
    providers: [
        ...APPLICATION_PROVIDERS, 
        AppStore
    ]
})
export class ApplicationComponent {}

3 回答

  • 94

    需要在模块的 entryComponents 部分声明要加载的所有组件"dynamically" . 换句话说,你应该得到类似的东西:

    @NgModule({
        imports: [BrowserModule, HttpModule, FormsModule, ReactiveFormsModule, ...MATERIAL_MODULES],
        declarations: [...APPLICATION_PIPES, ...APPLICATION_COMPONENTS, ...APPLICATION_DIRECTIVES, CygnusComponent,
            // Component declarations
            // TODO: refactor to appropriate modules
            ...
            ComponentDispatcherComponent,
            TextCellComponent,
            ...
        entryComponents: [TextCellComponent]
        bootstrap: [ApplicationComponent],
        providers: [...APPLICATION_PROVIDERS, AppStore]
    })
    export class ApplicationComponent{
    

    请注意,您需要在 declarationsentryComponents 部分列出 TextCellComponent .

  • 1

    您可能想要检查导入路径 . 在我的例子中,一个文件导入使用大写,而另一个使用小写 .

    //file 1
    import { IRComponent } from "./components/IR/IR.component";
    //file 2
    import { IRComponent } from "./components/ir/ir.component";
    

    赠品是在Chrome网络标签中,我注意到该文件被加载两次(每次拼写一次) .

  • 0

    即使您已在EntryComponents和Declarations中提供了Component,有时您也会遇到此问题 .

    在这些情况下,您只需输入此组件名称(此处为 TextCellComponent ),如下所示:

    declarations: [ 
            TextCellComponent // Declared above
            CygnusComponent,
            ComponentDispatcherComponent,
            ...
        ]
    

    这也应该在entryComponents中完成 .

    希望有所帮助 .

相关问题