0

THE SETUP

I'm teaching myself Angular with a simple app of my own: a game which will use routing, services, etc. On the landing page ( route for '/'), I want the header to hide. The header and router-outlet are together in the app-component like this (including some debug output in the brand):

<nav class="navbar navbar-default navbar-fixed-top" [hidden]="!showHeader">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="" [routerLink]="['/']">FARKLE! {{showHeader | json}}</a>
        </div>
    </div>
</nav>
<div class="container">
    <router-outlet></router-outlet>
</div>

The component class declares the boolean showHeader and attempts to update it when the route changes like this:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  showHeader: boolean;

  constructor(
    private router: Router
  ) {}

  ngOnInit () {
    this.showHeader = true;
    this.router.events.subscribe(this.setHeader());
  }

  private setHeader () {
    var showHeader = this.showHeader;
    return function (event) {
      if (event instanceof NavigationEnd) {
        showHeader = event.url === '/';
        console.log(event.url, showHeader, this.showHeader);
      };
    };
  }
}

The value of this.showHeader properly sets in ngOnInit and the header will show or not show correctly depending on how it is initialized. The console shows the event occurring during navigation and the value being determined correctly. The issue is in that in the context of the callback, this is no longer the component. So, I attempt to pass this.showHeader in by reference. BUT, showHeader is not reflected in the template (most likely because it is not actually getting into the scope of the event callback.

THE QUESTION

So, how do you affect the component scope from with the callback of the observable?

gkl
  • 199
  • 2
  • 11

2 Answers2

0

What I understood is, you're kind of doing closure, where the setHeader's returned function will be registered as subscription.

The setHeader's returned function should use Arrow function in order to persist correct this

private setHeader () {
    var showHeader = this.showHeader;
    //return function (event) {
    //should get changed to below line
    return (event) => { //Use Arrow function here.
      if (event instanceof NavigationEnd) {
        showHeader = event.url === '/';
        console.log(event.url, showHeader, this.showHeader);
      };
    };
}
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
0

You need to bind the this keyword to the setHeader function.

You can do that in 2 ways:

  1. use arrow => function

this.router.events.subscribe(() => this.setHeader());

  1. use bind

this.router.events.subscribe(this.setHeader.bind(this));

Alexander Ciesielski
  • 10,506
  • 5
  • 45
  • 66