0

Scenario: I have a header component and have a login-page component. I would like to call a function from the header component on the login-page component to update the header based on whether you logged in or not.

Question: Can someone please explain how I would go about doing this? I've tried using @ViewChild with no success. Furthermore, if I'm going about this the wrong way perhaps you can enlighten me on a better way?

Cheers!

import ...

@Component({
    selector: 'header',
    templateUrl: '/views/header.html',
    directives: [ROUTER_DIRECTIVES],
})

export class Header {

    constructor() {

    }

    public updateRight() {
        alert("nope");
    }

}


import ...


@Component({
    selector: 'login',
    templateUrl: '/views/login.html',
    providers: [HTTP_PROVIDERS],
})

export class Login {
    @ViewChild(Header) header: Header;

    constructor(http: Http) {
    }

    onSubmit() {
        // call function to update header stuffs
        this.header.updateRight();
    }

}

The main.ts template

<header></header>
<router-outlet></router-outlet>

The header.ts template

<div id="header-wrap">
    <div class="container">
        <div class="row">
            <div class="col-md-3">
                <h3><strong><a [routerLink]="['/Home']">HomePage</a></strong></h3>
            </div>
            <div class="col-md-6">
            </div>
            <div class="col-md-3" style="text-align: right;">
                <a [routerLink]="['/Login']">Log In</a>
                <a [routerLink]="['/Register']">Sign Up</a>
            </div>
        </div>
    </div>
</div>

The login.ts template

<div class="container padme">
    login
</div>
Zander17
  • 1,894
  • 5
  • 23
  • 31

1 Answers1

0

In fact, you can only leverage @ViewChild for elements that are contained into the template of the component. This applies if you have something like that (assuming that the selector is the Header component is header):

@Component({
  (...)
  template: `
    <header></header>
  `
})
export class Login {
  @ViewChild(Header) header: Header;
  (...)
}

Moreover the corresponding value won't be available in the component constructor but later:

View queries are set before the ngAfterViewInit callback is called.

So you could refactor your code like this:

@Component({
  (...)
  template: `
    <header></header>
  `
})
export class Login {
  @ViewChild(Header) header: Header;

  ngAfterViewInit() {
    this.header.someFunction();
  }
}

If you don't have this relation between the two components (and I think that it's the case - components at same level or on different component trees), you should use a shared service to make them communicate. You can leverage observables to implement a service bus...

See these questions at this level:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360