This is not intended to be a complete guide, but rather an overview of the basics to get you up and running so you can get to know Dynamic Themes
and how to use it with Angular Material 5
.
#Article Series:
- Creating Angular 5 application with Angular-cli
- Using
Angular Material
withAngular 5
- Deploy Angular 5 Application to Netlify
- Build
PWA
with Angular 5 App- Build Dynamic themes for
Angular Material
(You are here)- Using
FlexLayout
with Angular 5- Building
News
App usingAngular 5
Final Demo here
This article is based on the four previous articles so you have to read them first.
We'll turn our application to have dynamic themes, actually 2 themes ( light and dark one). Besides changing the theme dynamically, without having to refresh the page.
In the first article I used the argument --style scss
to select SCSS
as our default styling extension.
Now, create a file src/assets/styles/material-theme.scss
with the following code:
1@import "~@angular/material/theming"; 2 3@include mat-core(); 4 5$primary: mat-palette($mat-indigo); 6$accent: mat-palette($mat-pink, A200, A100, A400); 7$warn: mat-palette($mat-red); 8$theme: mat-light-theme($primary, $accent, $warn); 9 10@include angular-material-theme($theme);
Now, we have to import this material-theme.scss
in styles.scss
If you were following me and did what I did in the previous articles your styles.scss
file should have import
for Angular material theme
. But now we'll replace it with our new material theme
It should look like:
1@import "./src/styles/material-theme"; 2body { 3 margin: 0; 4}
Next, I want to put the controller of the dynamic theme in the navbar
, so I'll create a component for our navbar
. and a service to control the theme.
In your application root run:
1ng g component navbar --module app.module.ts
and don't forget the argument --module app.module.ts
I mentioned why in the previous articles.
We need to do several things
app.component.html
to src/app/navbar/navbar.component.html
navbar
from app.component.scss
to src/app/navbar/navbar.component.scss
.<app-navbar></app-navbar>
in app.component.html
material slide toggle
to our navbar componentHere's the code of each file
src/app/navbar/navbar.component.html
1<mat-toolbar color="primary"> 2 <mat-toolbar-row> 3 <span>Wb.Gy</span> <span className="example-spacer"></span> 4 <a className="example-link" routerLink="/" mat-button>Home</a> 5 <a className="example-link" routerLink="/posts" mat-button>Posts</a> 6 <mat-slide-toggle>Dark theme</mat-slide-toggle> 7 </mat-toolbar-row> 8</mat-toolbar>
src/app/navbar/navbar.component.scss
1.example-link { 2 padding: 0 14px; 3} 4.example-spacer { 5 flex: 1 1 auto; 6}
app.component.html
1<app-navbar></app-navbar> <router-outlet></router-outlet>
and app.component.scss
should be empty now.
Next we need to add our dark theme to material-theme.scss
Now it should look like:
1@import "~@angular/material/theming"; 2 3@include mat-core(); 4 5$primary: mat-palette($mat-indigo); 6$accent: mat-palette($mat-pink, A200, A100, A400); 7$warn: mat-palette($mat-red); 8$theme: mat-light-theme($primary, $accent, $warn); 9 10@include angular-material-theme($theme); 11 12// Our dark theme 13.dark-theme { 14 color: $light-primary-text; 15 $dark-primary: mat-palette($mat-yellow); 16 $dark-accent: mat-palette($mat-amber, A400, A100, A700); 17 $dark-warn: mat-palette($mat-red); 18 $dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn); 19 20 @include angular-material-theme($dark-theme); 21}
Let's check if our theme works or not
Open app.component.html
, we'll add two divs
and put all the code into them:
1<div className="dark-theme"> 2 <div className="mat-app-background"> 3 <app-navbar></app-navbar> 4 <router-outlet></router-outlet> 5 </div> 6</div>
Check your page now you should see the dark theme works!
Now let's create the theme service
1ng g service services/theme --module app.module.ts
this will create new folder under src/app
and new service named theme
To make our theme service
publish changes to our components we have to use rxjs
.
Let's edit our service:
src/app/services/theme.service.ts
1import { Injectable } from '@angular/core'; 2import { Subject } from 'rxjs/Subject'; 3 4@Injectable() 5export class ThemeService { 6 private _themeDark: Subject<boolean> = new Subject<boolean>(); 7 isThemeDark = this._themeDark.asObservable(); 8 9 setDarkTheme(isThemeDark: boolean) { 10 this._themeDark.next(isThemeDark); 11 } 12}
Now let's import our theme service
to our navbar
src/app/navbar/navbar.component.ts
1import { Component, OnInit } from '@angular/core'; 2import { ThemeService } from '../services/theme.service'; 3import { Observable } from 'rxjs/Observable'; 4 5@Component({ 6 selector: 'app-navbar', 7 templateUrl: './navbar.component.html', 8 styleUrls: ['./navbar.component.scss'] 9}) 10export class NavbarComponent implements OnInit { 11 12 isThemeDark: Observable<boolean>; 13 14 constructor(private themeService: ThemeService) { } 15 16 ngOnInit() { 17 this.isThemeDark = this.themeService.isThemeDark; 18 } 19 20 toggleDarkTheme(checked: boolean) { 21 this.themeService.setDarkTheme(checked); 22 } 23}
and In navbar.component.html
1<mat-toolbar color="primary"> 2 <mat-toolbar-row> 3 <span>Wb.Gy</span> <span className="example-spacer"></span> 4 <a className="example-link" routerLink="/" mat-button>Home</a> 5 <a className="example-link" routerLink="/posts" mat-button>Posts</a> 6 <mat-slide-toggle 7 [checked]="isThemeDark | async" 8 (change)="toggleDarkTheme($event.checked)" 9 >Dark theme</mat-slide-toggle 10 > 11 </mat-toolbar-row> 12</mat-toolbar>
The last thing is to add our theme service
to our app.component.ts
1import { Component, OnInit } from "@angular/core"; 2import { Observable } from "rxjs/Observable"; 3 4import { ThemeService } from "./services/theme.service"; 5 6@Component({ 7 selector: "app-root", 8 templateUrl: "./app.component.html", 9 styleUrls: ["./app.component.scss"] 10}) 11export class AppComponent implements OnInit { 12 isThemeDark: Observable<boolean>; 13 14 constructor(private themeService: ThemeService) {} 15 16 ngOnInit() { 17 this.isThemeDark = this.themeService.isThemeDark; 18 } 19}
One last thing in our app.component.html
1<div [ngClass]="{'dark-theme': isThemeDark | async}"> 2 <div className="mat-app-background"> 3 <app-navbar></app-navbar> 4 <router-outlet></router-outlet> 5 </div> 6</div>