javascriptangularangular2-hostbinding

Angular: toggle HostBinding from different component?


I have a component app-layout that holds a sidenav and a router outlet for my pages:

<div class="main-wrapper">
  <app-sidenav></app-sidenav>
  <main>
    <router-outlet></router-outlet>
  </main>
</div>

This app-layout has a HostBinding on it to set a class on it (the presence of a sidenav or not needs to change several things via css).

  @HostBinding('class.show-menu') hasSidebar;

A component loaded into the router outlet needs to have a button that toggle the value of hasSidebar so that the class will either be applied or not applied.

So, I set up a service to hold the boolean

import { Injectable } from '@angular/core';

@Injectable()
export class Globals {
  sidebar = true;
}

And I added it to the app-layout component above, like so

import { Component, OnInit, HostBinding } from '@angular/core';
import { Globals } from 'app/globals';

@Component({
  selector: 'app-layout-site',
  templateUrl: './layout.component.html'
})
export class LayoutComponent implements OnInit {
  @HostBinding('class.show-menu') hasSidebar;

  constructor(private globals: Globals) {
    this.hasSidebar = this.globals.sidebar;
  }

  ngOnInit() {}
}

Changing the value of the boolean manually (in code) shows it works. But now I need to toggle this value from the other component. In the other component, I have:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Globals } from 'app/globals';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
  private sidebar: boolean;

  constructor(private globals: Globals) {
    this.sidebar = globals.sidebar;
  }

  ngOnInit() {}

  toggleSidebar() {
    this.globals.sidebar = !this.globals.sidebar;
  }
}

And I create a button in this component to call the toggleSidebar function.

However, the app-layout component's hostbinding does not update and there for the class doesn't toggle.

What am I missing? I'm guessing there's currently no way for the app-layout component to "know" I've changed the variable. But I don't know how to bind it. I found this Stackblitz but it's for a bound string — how to do the same thing with a HostBinding?


Solution

  • You can ensure that hasSidebar is always up-to-date in LayoutComponent by making it a getter:

    @HostBinding('class.show-menu') get hasSidebar(): boolean {
      return this.globals.sidebar;
    }