Search code examples
angularsystemjs

angular 2: trying to load a component dynamically, getting: TypeError: Cannot read property 'parentInjector'


I am trying to load a component dynamically with angular2 and it's erroring out with:

EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'parentInjector' of undefined

this is the code:

@Component({
    selector: 'Notes5',
    template: `<span #extensionAnchor></span>`
 })

export class Notes5 extends NotesBase {
    constructor(private dynamicComponentLoader:DynamicComponentLoader, private NotesService:NotesService,
                protected sliderPanel:Sliderpanel,
                protected commBroker:CommBroker) {

        this.LoadComponentAsync("src/comps/app2/notes/NoteDynamic", "TestComponent", this.extensionAnchor);
    }

    @ViewChild('extensionAnchor', {read: ViewContainerRef}) extensionAnchor:ViewContainerRef;

    public LoadComponentAsync(componentPath:string, componentName:string, locationAnchor:ViewContainerRef) {
        System.import(componentPath)
            .then(fileContents => {
                console.log(fileContents);
                return fileContents[componentName]
            })
            .then(component => {
                this.dynamicComponentLoader.loadNextToLocation(component, locationAnchor)
            });
    }
}

any ideas?

regards

Sean


Solution

  • Your original error is caused by a mismatch between the actual class name and the name of the component you are trying to dynamicall render: I.E., if you are referencing TestComponent the class must also be named TestComponent.

    Your current error TypeError: Cannot read property 'parentInjector', is caused by trying to load content into the @ViewChild element before the view is rendered, since you are calling it in the constructor. You need to move your call further down the lifecycle, such as ngAfterViewInit.

    constructor(private dynamicComponentLoader:DynamicComponentLoader, 
                private NotesService:NotesService,
                protected sliderPanel:Sliderpanel,
                protected commBroker:CommBroker,
                private resolver: ComponentResolver) {
    }
    
    ngAfterViewInit() {
        this.LoadComponentAsync("src/comps/app2/notes/NoteDynamic", 
            "TestComponent", this.extensionAnchor);
    }
    

    Finally, since DynamicComponentLoader is deprecated, you should be using ComponentResolver instead:

    public LoadComponentAsync(componentPath:string, componentName:string, 
                              locationAnchor:ViewContainerRef) {
        System.import(componentPath)
            .then(fileContents => {
                console.log(fileContents);
                return fileContents[componentName]
            })
            .then(component => {
                this.resolver.resolveComponent(component).then(factory => {
                    locationAnchor.createComponent(factory, 0, locationAnchor.injector);
                });
            });
    }