DEV Community 👩‍💻👨‍💻

Muhammad Awais
Muhammad Awais

Posted on

Creating a Dark & Light Toggle Mode on your Angular App

Firstly, we have to make the theme-service in our angular app which contains the boolean Subject through which the dark mode is toggled from the components.

What is a Subject?

An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers.

import { Subject } from 'rxjs';
Enter fullscreen mode Exit fullscreen mode

after that, we have to initiate/declare the boolean Subject as pass it to the theme variable with asObservable() so that it can listen the the activity and toggle the theme

private _themeDark: Subject<boolean> = new Subject<boolean>();
isThemeDark = this._themeDark.asObservable();
Enter fullscreen mode Exit fullscreen mode

your theme-service should be like this,

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

@Injectable({
  providedIn: 'root'
})
export class ThemeService {

  white: string = '#ffffff';
  black: string = '#141313';

  private _themeDark: Subject<boolean> = new Subject<boolean>();

  isThemeDark = this._themeDark.asObservable();

  constructor() { }

  setDarkTheme(isThemeDark: boolean) {
    this._themeDark.next(isThemeDark);

    if (isThemeDark == true) {
      console.log('Dark Used');
      document.documentElement.style.setProperty('--white-color', this.black);
      document.documentElement.style.setProperty('--black-color', this.white);
      localStorage.setItem('dark', 'true');
    }
    else {
      console.log('Light Used');
      document.documentElement.style.setProperty('--white-color', this.white);
      document.documentElement.style.setProperty('--black-color', this.black);
      localStorage.setItem('dark', 'false');
    }
  }

}
Enter fullscreen mode Exit fullscreen mode

And we have to use that service in any component to toggle the app theme.

<!-- sample.component.html -->
<div class="text-right">
  <div class="custom-control custom-switch">
    <mat-checkbox type="checkbox" 
          class="custom-control-input" 
          id="darkMode" 
          [checked]="isThemeDark | async"
          (change)="toggleDarkTheme($event)">
      <label class="custom-control-label" for="darkMode"></label>
      <a class="text-capitalize">Dark Mode</a>
    </mat-checkbox>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, in your components .ts file, import the theme-service you have, and import the observable from rxjs

import { ThemeService } from '../../shared/services/theme/theme.service';
import { Observable } from 'rxjs';
Enter fullscreen mode Exit fullscreen mode

And your components .ts file should be like this, which actually contains the toggle handler that will trigger the subject of theme-service observable.

import { Component, OnInit } from '@angular/core';
import { ThemeService } from '../../shared/services/theme/theme.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-sample',
  templateUrl: './sample.component.html',
  styleUrls: ['./sample.component.scss']
})
export class SampleComponent implements OnInit {
  isThemeDark: Observable<boolean>;

  constructor(
    private themeService: ThemeService
  ) {}

  ngOnInit() {
    this.isThemeDark = this.themeService.isThemeDark;
  }

  toggleDarkTheme(checked) {
    this.themeService.setDarkTheme(checked.checked);
    // console.log("checked >", this.isThemeDark);
    console.log("checked >", checked.checked);
  }

}
Enter fullscreen mode Exit fullscreen mode

Github Source

https://gist.github.com/muhammadawaisshaikh/9b62e76a3827a7478c59dc30e0eaa8a1

That's All :)

Top comments (2)

Collapse
 
kdipippo profile image
Kathryn DiPippo

Thanks for this tutorial! Worked great!

Collapse
 
thisdotmedia_staff profile image
This Dot Media

Really good to know! Thanks for showing us how to go about this Muhammad 😁

Want to rep DEV and be comfy at the same time?

Check out our classic DEV shirt — available in multiple colors.