Friday, 5 October 2018

How to subscribe to Observable of Component injected via @angular/cdk/portal?

I'm trying to implement a basic (very basic) modal implementation. I've got a ModalService and a ModalComponent.

The ModalService creates an instance of the ModalComponent and injects it into the page using the @angular/cdk/portal.

I can get the modal to display just fine :-)

The ModalComponent has an Observable property that I want the ModalService to subscribe to so that when the 'close' button is clicked within the modal, a value can be emitted and the ModalService can close the modal.

However, when the component emits the value, the Service is not acting on it. From the Service side, it looks like I'm subscribed, but from the Component side, it shows 0 observers.

I thought maybe I could use a typical @Output() EventEmitter, but I'm not sure to hook that up since the in the modal class, since the child element doesn't exist initially.

I'm thinking maybe my component reference is not quite right (maybe I have 2 different ones?). I'm trying suggestion from this answer

Any ideas what I'm doing wrong?

Service

export class ModalService {

    private modalPortal: ComponentPortal<any>;
    private bodyPortalHost: DomPortalHost;

    constructor(private componentFactoryResolver: ComponentFactoryResolver,
                private appRef: ApplicationRef,
                private injector: Injector) {
    }

    showModal(modalName: string) {

        // set up the portal and portal host
        this.modalPortal = new ComponentPortal(ModalComponent);
        this.bodyPortalHost = new DomPortalHost(
            document.body,
            this.componentFactoryResolver,
            this.appRef,
            this.injector);

        // display the component in the page
        let componentRef = this.bodyPortalHost.attach(this.modalPortal);


        // listen for modal's close event
        componentRef.instance.onModalClose().subscribe(() => {
            console.log('I will be very happy if this this gets called, but it never ever does');
            this.closeModal();
        });

        // console.log(componentRef.instance.onModalClose()) shows 1 subscriber.
    }

    closeModal() {
        this.bodyPortalHost.detach();
    }
}

Component

export class ModalComponent {

    private modalClose: Subject<any> = new Subject();

    onModalClose(): Observable<any> {
        return this.modalClose.asObservable();
    }

    closeModal() {
        // console.log(this.onModalClose()) **shows zero observers**   :-(
        this.modalClose.next();
        this.modalClose.complete();
    }
}

Also, if I happen to be asking the wrong question, meaning there's a better overall approach, I'm open to suggestions. :-)

Thanks!



from How to subscribe to Observable of Component injected via @angular/cdk/portal?

No comments:

Post a Comment