Switch themes in angular material 5

前端 未结 4 1362
一整个雨季
一整个雨季 2020-12-08 11:06

I been reading a few articles on this but they seem to be conflicting in several different ways. I am hoping to re-create the same theme switching as the angular material do

相关标签:
4条回答
  • 2020-12-08 11:43

    You have to use the getContainerElement method of OverlayContainer. Here's some example usage:

    this.overlay.getContainerElement().classList.add('my-theme');
    

    As for your style files, I strongly suggest removing this line for both custom-theme.scss and light-custom-theme.scss (you only need it for your classes in this case):

    @include angular-material-theme($custom-theme); // Remove this line from custom-theme.scss and light-custom-theme.scss
    

    If you also want to toggle the theme for your app, you should probably use this in the same toggleTheme method:

    toggleTheme(): void {
      if (this.overlay.classList.contains("custom-theme")) {
        this.overlay.classList.remove("custom-theme");
        this.overlay.classList.add("light-custom-theme");
      } else if (this.overlay.classList.contains("light-custom-theme")) {
        this.overlay.getContainerElement().classList.remove("light-custom-theme");
        this.overlay.classList.add("custom-theme");
      } else {
        this.overlay.classList.add("light-custom-theme");
      }
      if (document.body.classList.contains("custom-theme")) {
        document.body.classList.remove("custom-theme");
        document.body.classList.add("light-custom-theme");
      } else if (document.body.classList.contains("light-custom-theme")) {
        document.body.classList.remove("light-custom-theme");
        document.body.classList.add("custom-theme");
      } else {
        this.overlay.classList.add("light-custom-theme");
      }
    }
    
    • More info on theming
    • Stackblitz demo (For the demo, I had to nest the app in a Sidenav)
    0 讨论(0)
  • 2020-12-08 11:54

    With reference to @Edric's solution

    Used local-storage to retain the selected theme.

    Here is my Github Link where I have updated the working code:~ Angular Material Theme Changer

    Hope this is also helpful.

    0 讨论(0)
  • 2020-12-08 11:55

    You cam always check how the theme picker is being implemented in https://material.angular.io/ and just do the same https://github.com/angular/material.angular.io/tree/master/src/app/shared/theme-picker by doing so you will have the everlasting solution as in case any breaking changes you always can lookup material docs source how to fix.

    0 讨论(0)
  • 2020-12-08 12:07

    Here's an alternative solution for Angular 5.1+/Angular Material 5.0+.

    *Edit: As noted, this still works in Angular 7+.

    Working editable example - https://stackblitz.com/edit/dynamic-material-theming

    In theme.scss, include a default theme(notice it isn't kept under a class name - this is so Angular will use it as the default), and then a light and dark theme.

    theme.scss

    @import '~@angular/material/theming';
    @include mat-core();
    
    // Typography
    $custom-typography: mat-typography-config(
      $font-family: Raleway,
      $headline: mat-typography-level(24px, 48px, 400),
      $body-1: mat-typography-level(16px, 24px, 400)
    );
    @include angular-material-typography($custom-typography);
    
    // Default colors
    $my-app-primary: mat-palette($mat-teal, 700, 100, 800);
    $my-app-accent:  mat-palette($mat-teal, 700, 100, 800);
    
    $my-app-theme: mat-light-theme($my-app-primary, $my-app-accent);
    @include angular-material-theme($my-app-theme);
    
    // Dark theme
    $dark-primary: mat-palette($mat-blue-grey);
    $dark-accent:  mat-palette($mat-amber, A200, A100, A400);
    $dark-warn:    mat-palette($mat-deep-orange);
    
    $dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
    
    .dark-theme {
      @include angular-material-theme($dark-theme);
    }
    
    // Light theme
    $light-primary: mat-palette($mat-grey, 200, 500, 300);
    $light-accent: mat-palette($mat-brown, 200);
    $light-warn: mat-palette($mat-deep-orange, 200);
    
    $light-theme: mat-light-theme($light-primary, $light-accent, $light-warn);
    
    .light-theme {
      @include angular-material-theme($light-theme)
    }
    

    In the app.component file, include OverlayContainer from @angular/cdk/overlay. You can find Angular's documentation for this here https://material.angular.io/guide/theming; though their implementation is a little different. Please note, I also had to include OverlayModule as an import in app.module as well.

    In my app.component file, I also declared @HostBinding('class') componentCssClass; as a variable, which will be used to set the theme as a class.

    app.component.ts

    import {Component, HostBinding } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { OverlayContainer} from '@angular/cdk/overlay';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
    })
    export class AppComponent {
    
      constructor(public overlayContainer: OverlayContainer) {}
    
      @HostBinding('class') componentCssClass;
    
      onSetTheme(theme) {
        this.overlayContainer.getContainerElement().classList.add(theme);
        this.componentCssClass = theme;
      }
    
    }
    

    app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { HttpClientModule } from '@angular/common/http';
    
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { MatCardModule } from '@angular/material/card';
    import { MatButtonModule } from '@angular/material/button';
    
    import { AppComponent } from './app.component';
    
    import { OverlayModule} from '@angular/cdk/overlay';
    
    @NgModule({
      declarations: [
        AppComponent,
      ],
      imports: [
        BrowserModule,
        HttpClientModule,
        BrowserAnimationsModule,
        MatCardModule,
        MatButtonModule,
        OverlayModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    Finally, call the onSetTheme function from your view.

    app.component.html

    <button mat-raised-button color="primary" (click)="onSetTheme('default-theme')">Default</button>
    <button mat-raised-button color="primary" (click)="onSetTheme('dark-theme')">Dark</button>
    <button mat-raised-button color="primary" (click)="onSetTheme('light-theme')">Light</button>
    

    You might consider using an observable so that the functionality would be more dynamic.

    0 讨论(0)
提交回复
热议问题