Mark
Mark

Reputation: 35

angular2 typescript call method on parent from dynamically loaded component

I am trying to call a parent method from a dynamically loaded component. I am using the dynamic component loader solution from the Angular cookbook https://angular.io/guide/dynamic-component-loader

What I try to accomplish is to call a deleteBanner method on the parent from the loaded component.

I added a eventEmitter on the loaded components (HeroJobAdComponent and HeroProfileComponent) and try to catch the event (deleteBanner) in the AdBannerComponent and call the local method on deleteBanneronParent in the AdBannerComponent.

The eventEmitter in the loaded component:

export class HeroProfileComponent implements AdComponent {
  @Input() data: any;
  @Output() deleteBanner: EventEmitter<string> = new 
  EventEmitter<string>();

  removeBanner() {
    console.log('removeBanner on HeroProfileComponent invoked');
    this.deleteBanner.emit(null);
  }
}

and catching the event in the parent:

<div ad-host (deleteBanner)="deleteBanneronParent()"></div>

The local method on the loaded components is invoked but for some reason its not propagating to the parent component. Any idea what I am missing here?

https://plnkr.co/edit/NzdkaLSEiAmlNnRyN5BW

Upvotes: 2

Views: 1226

Answers (1)

hagner
hagner

Reputation: 1050

Since you are using a directive to host your dynamic components the propagation of the event is lost in the directive and the parent never gets any event.

The loadComponent() method that you are using to insert the content into the directive already takes a ComponentRef and load the content. You can use this ComponentRef to subscribe to events as well.

Extend the interface for the AdComponent interface:

import { EventEmitter } from '@angular/core';

export interface AdComponent {
    data: any;
    deleteBanner: EventEmitter<string>;
}

And then subscribe to events from your component:

loadComponent() {
    this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length;
    let adItem = this.ads[this.currentAddIndex];

    let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);

    let viewContainerRef = this.adHost.viewContainerRef;
    viewContainerRef.clear();

    let componentRef = viewContainerRef.createComponent(componentFactory);
    (<AdComponent>componentRef.instance).data = adItem.data;

    //Subscribe to the events here 
    (<AdComponent>componentRef.instance).deleteBanner.subscribe(evt => console.log(`Event: ${evt}`));
}

Upvotes: 1

Related Questions