5

I'm creating an app with Angular 2 using the routing features, and I have a popup component that is rendered by one of the higher up routes, and I want to open it on a click event in a component that is rendered by one of the deeper routes.

For example, let's say I have a base router with a template containing the popup:

@Component({
    selector: 'application',
    template: '<router-outlet></router-outlet><popup-component></popup-component>',
    directives: [PopupComponent]
})
@RouteConfig([
    { ... },
    { ... }
])
export class AppRoute { }

And a simple popup component with an open method:

@Component({
    selector: 'popup-component',
    template: '<div [class.show]="isVisible">This is a popup.</div>'
})
export class PopupComponent {
    public isVisible: boolean = false;
    show() {
        this.isVisible = true;
    }
}

How can I call this show method on that specific PopupComponent that was already rendered by the AppRoute from another component that resides somewhere down in the routing tree?

I have tried using dependency injection like this:

@Component({
    selector: 'my-component',
    template: '<button (click)="showPopup()"></button>'
})
export class MyComponent {
    constructor(private popup: PopupComponent) { }
    showPopup() {
        this.popup.show();
    }
}

But this just creates a new instance of the PopupComponent that isn't actually rendered yet. How can I call the one that is rendered by the AppRoute?

1 Answer 1

8

You need a shared service

import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Rx';
export class PopupService{
   show:Subject<boolean> = new Subject();
}

Add the service to providers in AppRoute

@Component({
    providers:[PopupService],
    selector: 'application',
    ...
])
export class AppRoute { }

Inject the service to popup-component and subscribe to the show subject.

@Component({
    selector: 'popup-component',
    template: '<div [class.show]="isVisible">This is a popup.</div>'
})
export class PopupComponent {
    public isVisible: boolean = false;
    constructor(private popup: PopupService) {
      popup.show.subscribe( (val:boolean) => this.isVisible = val );
    }
}

Inject it to any component where you want to show the popup, call next on the show subject;

@Component({
    selector: 'my-component',
    template: '<button (click)="showPopup()"></button>'
})
export class MyComponent {
    constructor(private popup: PopupService) { }
    showPopup() {
        this.popup.show.next(true);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.