Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
648 views
in Technique[技术] by (71.8m points)

angular - Angular2 RC 5. No component factory found for dynamically loaded components

I'm trying to update my dynamic component loader from RC4 to RC5 since the ComponentResolver is deprecated. I've updated the loader to the following

@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();
        }
    }
}

And attempt to dynamically load the following component into the 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');
        });
    }
}

Yet when I do this with my TextCellComponent or any other component within the app I get the following error

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 

I've completed the steps in

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

but I seem to be missing something. I've tried adding the components to the bootstrapping and defining them globally with no luck. Any suggestions would be helpful.

EDIT

Adding the module definition

@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 {}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

All components about to be loaded "dynamically" need to be declared in the entryComponents section of your module. In other words you should end up with something like:

@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{

Please note that you need to list the TextCellComponent in both the declarations and entryComponents section.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...