1

I have a header.component.ts that should populate a user name once the user is logged in. I'd like to be able to call a function/method on the header.component class from the mainMenuComponent.

This is in the context of angular2. So when I route to my mainmenu.component it should call the header.component to set the user name.

Here is my layout:

app.component:

@Component({
    selector: 'myapp',
    template:`<header userName="{{userName}}"></header>
                        <router-outlet></router-outlet>`,
    directives: [ROUTER_DIRECTIVES, HeaderComponent]   
})

@RouteConfig([
  {path:'/', name:'Login', component: LoginComponent, useAsDefault: true},
  {path:'/mainmenu', name:'MainMenu', component: MainMenuComponent},])

header.component:

@Component({
    selector: 'header',
    templateUrl: 'header.html'     
})

export class HeaderComponent {
       @Input() userName;

       updateHeaderUserName(userName:string) {
                this.userName = userName;
           }
}

login.component:

onSubmit() {
   this._router.navigate( ['MainMenu', {userName: 'John Doe'}] );
}

mainMenuComponent:

export class MainMenuComponent implements OnInit { 

    constructor(
        private _routeParams:RouteParams){}

        ngOnInit() {
          // CAN I CALL THIS FUNCTION OFF THE HEADER.COMPONENT HERE???
          updateHeaderUserName(this._routeParams.get('userName'));     

        }

}

As you can tell from the code I've done attempted a solution using routing params but I can pass the userName all I want when routing to facilitate route component communication but it's not clear if the HeaderComponent is in memory how I call a public function it has?

Justin
  • 859
  • 4
  • 15
  • 30
  • 2
    I think there is no relationship between `header & main components` else you could have used `EventEmitter` to call `updateHeaderUserName` method. Now, as per my knowledge I think you should think of using `service` more specific `shared service among components` in Angular2. – micronyks Feb 11 '16 at 05:02
  • I actually tried EventEmitter and it didn't work and I was wondering why until I took a look at how
    and were not related. I briefly toyed with putting instead the
    but you comment just confirms what I suspected about the scoping of the elements and it makes sense!
    – Justin Feb 11 '16 at 15:29

1 Answers1

2

As @micronyks said, the shared service seems to be the solution. The important thing not to miss is to share the same instance of the service by components.

You can define this service within providers when bootstrapping your application:

bootstrap(MainComponent, [ SharedService ]);

Then you can inject it into both components, LoginComponent and MainMenuComponent. This way you can share the data without calling an updateHeaderUserName on a component you can't reference...

For more detils about dependency injection and hierarchical injectors, you could have a look at this answer:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thank you! I've been racking my brain trying to think of scope between the
    and the to explain why EventEmitter would not be working. Been reading to get more in-depth knowledge of routing but a simple service was the answer I couldn't find.
    – Justin Feb 11 '16 at 15:06
  • once I have my shared service how will the component that uses it know when the value the service contains has changed? If my MainMenuComponent updates SharedService.userName how will the template for HeaderComponent know ShareService.userName has been updated? – Justin Feb 11 '16 at 17:36
  • To do that, you can add an `EventEmitter` property in it. This way, you can implement a `updateHeaderUserName` method in the service: `updateHeaderUserName(username) { this.usernameEmitter.emit(username); }`. On this other side, components can subscribe on this emitter to be notified: `this.usernameEmitter.subscribe((newValue) => { console.log('username updated'); });` – Thierry Templier Feb 11 '16 at 17:40
  • 1
    You could have a look at the Mark's great answer regarding such concept: http://stackoverflow.com/questions/34376854/delegation-eventemitter-in-angular2/34402436 – Thierry Templier Feb 11 '16 at 17:43
  • OK! I got as far as using an EventEmitter on my SharedService but I wasn't sure how to catch it/watch it. Need to familiarize myself with the Observable library. – Justin Feb 11 '16 at 19:11
  • One gotcha (I got it working) make sure the components you have use the "selector" property on the @Component. I had everything wired up like the example (you provided in the comments above) and it didn't work. I knew prior to this that with the selector missing you got an element which I assumed was innocuous but once I added it everything just worked. Now I need to go back through my other routes and make sure those components have a selector. – Justin Feb 11 '16 at 20:42