Menggunakan Material Theme

Pada modul ini kita akan menggunakan theme. Menu toggle akan disimpan pada toolbar, namun proses perubahan theme perlu dilakukan pada parent component, dalam hal ini adalah sidenav component.

Jadi pada toolbar component perlu dilakukan event emiter.

Buka file toolbar.component.html, tambahkan menu untuk toggle theme.

<mat-toolbar color="primary">
    <button class="sidenav-toggle" mat-button (click)="toggleSidenav.emit()">
        <mat-icon>menu</mat-icon>
    </button>
    <span>Contact Manager</span>
    <!-- menambahkan menu pada toolbar -->
    <span class="example-spacer"></span>
    <button mat-icon-button [matMenuTriggerFor]="menu">
      <mat-icon>more_vert</mat-icon>
    </button>
    <mat-menu #menu="matMenu">
      <button mat-menu-item (click)="openAddContactDlg()">Add Contact</button>
      <button mat-menu-item (click)="toggleTheme.emit()">Change Theme</button>
    </mat-menu>
</mat-toolbar>

Kemudian buka file toolbar.component.ts, tambahkan code untuk handling toggleTheme.

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AddContactDialogComponent } from '../add-contact-dialog/add-contact-dialog.component';

@Component({
  selector: 'app-toolbar',
  templateUrl: './toolbar.component.html',
  styleUrls: ['./toolbar.component.scss']
})
export class ToolbarComponent implements OnInit {
  @Output() toggleSidenav = new EventEmitter<void>();
  // handling click event emiter toggleTheme
  @Output() toggleTheme = new EventEmitter<void>();

  constructor(private dialog : MatDialog) { }

  ngOnInit(): void {
  }

  openAddContactDlg(){
    let dialogRef = this.dialog.open(AddContactDialogComponent, {
      width: '400px'
    });

    dialogRef.afterClosed().subscribe(result=>{
      console.log(result);
    });
  }


}

Kemudian buka file sidenav.component.html, tambahkan code event untuk toggleTheme

<!-- tambahkan binding property untuk merubah theme -->
<mat-drawer-container class="app-sidenav-container" autosize [class.dark-theme]="isDarkTheme">
    <mat-drawer #drawer class="app-sidenav mat-elevation-z10" [mode]="isScreenSmall ? 'over' : 'side' " [opened]="!isScreenSmall">
        <mat-toolbar color="primary">
            <span>Contact</span>
        </mat-toolbar>
        <mat-nav-list>
            <mat-list-item *ngFor="let user of users | async">
                <!-- tambahkan router link pada element a -->
               <a matLine [routerLink]="['/contactmanager', user.id]">
                    <mat-icon svgIcon="{{ user.avatar }}"></mat-icon>   {{ user.name }}
                </a>
            </mat-list-item>
        </mat-nav-list>
    </mat-drawer>
  
    <div class="app-sidenav-content">
        <app-toolbar (toggleTheme)="toggleTheme()" (toggleSidenav)="drawer.toggle()"></app-toolbar>
        <div class="wrapper">
            <router-outlet></router-outlet>
        </div>
    </div>
  
</mat-drawer-container>

Kemudian buka file sidenav.component.ts, buat method untuk handling toggleTheme

import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Observable } from 'rxjs';
import { UserService } from '../../services/user.service';

import { User } from '../../models/user';
import { Router } from '@angular/router';
import { MatDrawer, MatSidenav } from '@angular/material/sidenav';

const SMALL_WIDTH_BP = 720;


@Component({
  selector: 'app-sidenav',
  templateUrl: './sidenav.component.html',
  styleUrls: ['./sidenav.component.scss']
})
export class SidenavComponent implements OnInit {
  public isScreenSmall! : boolean;
  users! : Observable<User[]>;
  //property darkTheme
  isDarkTheme : boolean = false;

  //tambahkan viewchild untuk akses sidenav
  @ViewChild(MatDrawer) drawer! : MatDrawer;

  //inject router
  constructor(private breakpointObs : BreakpointObserver, private userSrv : UserService, private router: Router) { }

  ngOnInit(): void {
    this.breakpointObs
    .observe([`(max-width: ${SMALL_WIDTH_BP}px)`])
    .subscribe((state: BreakpointState)=>{
      this.isScreenSmall = state.matches;
    });

    this.users = this.userSrv.users; 
    this.userSrv.loadAllUser();

    this.users.subscribe(data =>{
      //modifikasi untuk menampilkan user idx pertama
      if(data.length>0) this.router.navigate(['/contactmanager', data[0].id]);
    });

    //menutup sidenav setelah user dipilih.
    this.router.events.subscribe(()=>{
      if(this.isScreenSmall){
        this.drawer.close();
      }
    });

  }

  //method toggle theme
  toggleTheme(){
    this.isDarkTheme = !this.isDarkTheme;    
  }

}

Terakhir, kita perlu buat css untuk darktheme diatas

// @import '@angular/material/prebuilt-themes/indigo-pink.css';

@use '@angular/material' as mat;
@include mat.core();

$candy-app-primary: mat.define-palette(mat.$indigo-palette);
$candy-app-accent:  mat.define-palette(mat.$pink-palette, A200, A100, A400);
$candy-app-warn:    mat.define-palette(mat.$red-palette);

$candy-app-theme: mat.define-light-theme(
    $candy-app-primary, $candy-app-accent, $candy-app-warn);

@include mat.all-component-themes($candy-app-theme);

.dark-theme {
    $primary-dark: mat.define-palette(mat.$pink-palette, 700);
    $accent-dark: mat.define-palette(mat.$green-palette);
    $warn-dark: mat.define-palette(mat.$red-palette);

    $theme-dark: mat.define-dark-theme($primary-dark, $accent-dark, $warn-dark);

    @include mat.all-component-themes($theme-dark);
}

html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }

Sesuai ekspektasi, sekarang kita bisa melakukan perubahan theme.

Masih banyak component angular material, pada tutorial ini kita hanya bahas beberapa komponen dasar yang umum digunakan pada aplikasi.

Diharapkan, setelah mengikuti tutorial ini, mempunyai gambaran bagaimana menggunakan Angular material.

Dengan berakhirnya modul ini, tutorial Angular Material telah selesai. Semoga bermanfaat.

Sharing is caring:

Leave a Comment