Skip to content Skip to sidebar Skip to footer

Toggle A Class By A Button From Header Component That Affect Main App Component By Angular 6+

My app by Angular simply starts with index.html: I would like it to be switched between Dark/Light by toggling betwe

Solution 1:

You're pretty close! I would highly recommend using a service so that you can effectively share state between components.

Basically what it looks like is a service:

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

@Injectable({
    providedIn: 'root'
})
export classThemeService {

    /**
     * Variable to hold our setting.
     */public darkMode: boolean;

    /**
     * Enable/disable "dark mode" by flipping the bit.
     */publictoggle(): void {

        this.darkMode = !this.darkMode;

    }

}

and the component:

<div class="wrapper" [class.dark-mode]="themeService.darkMode">

    <divclass="text">

        Dark Mode Enabled? {{ themeService.darkMode ? 'YES' : 'NO' }}

    </div><divclass="button">

        Parent Component

        <button (click)="themeService.toggle()">Toggle!</button></div><app-child></app-child>

</div>

You will use dependency injection to "expose" the ThemeService like so:

import { Component }    from'@angular/core';
import { ThemeService } from'./theme.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: [ './app.component.scss' ]
})
exportclassAppComponent {

    /**
     * Inject the theme service which will be called by our button (click).
     *
     * @param {ThemeService} themeService instance.
     */publicconstructor(public themeService: ThemeService) {

    }

}

By using a service you can not only share state but also wire up more properties like font-size, etc from a central location.

I have a brief tutorial explaining how to wire things up at https://matthewdavis.io/theme-service accompanied by the project repo https://github.com/mateothegreat/ng-byexamples-theme-service.

Hope this helps you along your journey. Feel free to ask questions!

Solution 2:

Components and their variables are scoped in Angular. This means, that a public variable in your component like isDarkMode is only known by the component itself and the template. There's no global representation of that variable.

While this works:

<app-header><div [ngClass]="{'dark-mode': isDarkMode}"></app-header>

This won't:

<body [ngClass]="{'dark-mode': isDarkMode}"></body>

What you can do is to set the class of the body-element in your component. But keep in mind that you should avoid manipulating the DOM directly and that your application should be platform agnostic.

That's why you should use Angular's dependency injection:

import { Component, OnInit, Renderer2, Inject } from'@angular/core';
import { DOCUMENT } from'@angular/common';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.less']
})

exportclassHeaderComponentimplementsOnInit {
  darkMode: boolean = false;

  constructor(@Inject(DOCUMENT) privatedocument: Document,
    private renderer: Renderer2,
  ) {}

  ngOnInit() {}

  toggleDarkMode() {
    this.darkMode = !this.darkMode;

    if (this.darkMode) {
      this.renderer.addClass(this.document.body, 'dark-mode');
    } else {
      this.renderer.removeClass(this.document.body, 'dark-mode');
    } 
  }
}

Now only the HeaderComponent can change the class. You should make this more versatile by using a service, so that you can do things like:

  • change the mode from any place in your application
  • through events make it possible for other components to be informed when the mode is changed

Post a Comment for "Toggle A Class By A Button From Header Component That Affect Main App Component By Angular 6+"