6

I have an issue where the EventEmitter does not output the value to parent component. Here is how i am setup.

main.component.ts (short version)

...     

@Component({
selector: 'my-app',
templateUrl: '/app/views/main.ejs',
directives: [ROUTER_DIRECTIVES],
providers:[AuthService],
inputs:['userLoggedIn']
})

@RouteConfig([
{path:'/logout', name: 'Logout', component: AuthComponent},

])

export class AppComponent implements OnInit, CanReuse{  

    constructor(private _auth_service: AuthService){

         this._auth_service.authChanged.subscribe(data=>this.authChangedHandler(data));

    }

    public authChangedHandler($event){

        alert($event);

    }

}

...

auth.component.ts (short version)

export class AuthComponent implements OnInit, CanReuse{

public loggedIn = false;

public user = {};

@Output()
authChanged: EventEmitter<string>;

public selectedTab = "/login";

    constructor(private _router: Router, private _location:Location,private _http: Http, private _auth_service: AuthService){

        this.authChanged = new EventEmitter();

        this.authChanged.emit("authChanged");

    }

}

main.ejs (short version)

<nav (authChanged)="authChangedHandler($event)"></nav>
<router-outlet></router-outlet>

auth.service.ts

export class AuthService {

public authChanged: EventEmitter<string>;

constructor(private _http: Http){

    this.authChanged = new EventEmitter();
    this.authChanged.emit("authChanged");

    }

}

EDIT: I have added AuthService code which i inject into main component. It should work now but does not.

xmaestro
  • 1,084
  • 2
  • 16
  • 44
  • Did you get a solution for it ? I am also looking to capture an event which is emitted from the component added in @RouteConfig – Sanjeev Feb 20 '16 at 03:26
  • @Sanjeev Yes i did. I used Service Events. I have a created a plunker here (https://plnkr.co/edit/WZ5HbvBP5LMSqZQtixoG?p=preview) – xmaestro Feb 20 '16 at 05:41
  • The idea is to inject a Service at bootstrap and that service will contain the eventemitter which every component can subscribe to, globally. – xmaestro Feb 20 '16 at 05:42
  • thanks @R. Hussain: but it ll be great if there is a way to bubble up the event. – Sanjeev Feb 20 '16 at 08:57

2 Answers2

14

Events emitted by EventEmitter don't bubble. If the element is added to a router-outlet only the router-outlet receives the event but not the element containing the router-outlet.

You could use a shared service to communicate between the parent and the child element.

For shared service see

If you register the shared service in the providers: [] list of the parent component, the service is shared only between the parent element and all of its descendants. If you only add it to bootstrap(MyApp, [ ..., SharedService]) the whole application shares one instance.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Could you please be more elaborate about the shared service? Maybe some code? – xmaestro Feb 12 '16 at 13:46
  • Yes i saw and i opted for Service Events and made changes to above code. Please see my edits. – xmaestro Feb 12 '16 at 14:12
  • If you emit the event in the constructor of the `AuthService` the event is alredy sent before `AppComponent` can subscribe. For the test wrap the `emit(event)` in `AuthService` in a `setTimeout()` to give `AppComponent` time to subscribe. In a real-world application it would fire later anyway. – Günter Zöchbauer Feb 12 '16 at 14:15
  • Well, i have already tried emitting inside a `logout` method in AuthService but to no avail :( – xmaestro Feb 12 '16 at 14:28
  • 1
    @GünterZöchbauer: you are right, but isn't there any way to bubble up the event to the element containing the router outlet ? – Sanjeev Feb 20 '16 at 08:55
  • I think the way to go is a shared service containing an EventEmitter, where the child invokes the event and the parent listens. – Günter Zöchbauer Feb 20 '16 at 08:57
1

In fact, the nav isn't the parent component of the AuthComponent one. The latter is involved in routing (see router-outlet). That's why you can't receive the event for the registered expression on the nav element in the HTML.

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Please see my edits. The `nav` issue should not matter now since i'm using Service Events. Right? – xmaestro Feb 12 '16 at 14:12
  • Yes, but you should use this: `this._auth_service.authChanged.emit('authChanged');` ;-) to trigger the event... – Thierry Templier Feb 12 '16 at 14:18
  • But i emit it from the service. Not from the component. – xmaestro Feb 12 '16 at 14:27
  • Oh sorry! Perhaps your service isn't completely a shared one (I mean by the whole application). To be sure, set it as provider when bootstrapping your application: `bootstrap(AppComponent, [ AuthService ]);`. Don't forget to remove it from `providers` attributes you can have at the level of your components. This is because of hierarchical injectors. See this answer for more details: http://stackoverflow.com/questions/34804298/whats-the-best-way-to-inject-one-service-into-another-in-angular-2-beta/34807397. – Thierry Templier Feb 12 '16 at 14:37