1
votes

I'm trying to achieve that the background of my app is a color defined by the currently used theme. This does not really work.

What I've tried: Angular Material2 theming - how to set app background?. I've tried to use the accepted solution of this posting but for me only the background of all components is set and gets overwritten by the theme. I don't know how to handle it.

How it looks like (white part with no content should be dark as well): enter image description here

I've copied the theming action like in this tutorial and everything works fine there: https://medium.com/grensesnittet/dynamic-themes-in-angular-material-b6dc0c88dfd7

app.component.html:

<div
  [ngClass]="{'default-theme': (selectedTheme | async) === 'default-theme', 'dark-theme': (selectedTheme | async) === 'dark-theme', 'light-theme': (selectedTheme | async) === 'light-theme', 'nature-theme': (selectedTheme | async) === 'nature-theme'}">
  <div class="mat-app-background">
    <app-header></app-header>
    <router-outlet></router-outlet>
  </div>
</div>

index.html:

<body class="mat-app-background">
  <app-root>
  </app-root>
</body>

material-theme.scss:

@import "~@angular/material/theming";
@import "./component-themes";

@include mat-core();

$primary: mat-palette($mat-indigo);
$accent: mat-palette($mat-pink, A200, A100, A400);
$warn: mat-palette($mat-red);
$theme: mat-light-theme($primary, $accent, $warn);

@include angular-material-theme($theme);
@include component-themes($theme);

.dark-theme {
  color: $light-primary-text;
  $dark-primary: mat-palette($mat-grey, 700, 300, 900);
  $dark-accent: mat-palette($mat-blue-grey, 400);
  $dark-warn: mat-palette($mat-red, 500);
  $dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
  $bp: mat-palette($mat-red);

  @include angular-material-theme($dark-theme);
  @include component-themes($dark-theme);
}

styles.scss:

@import "./material-theme";
@import "~@angular/material/theming";

body {
  margin: 0;
  font-family: Roboto, sans-serif;
  // background-color: mat-color($bp);
}

Themes are set through the app-component.ts:

  ngOnInit(): void {
    this.themeService.setTheme(localStorage.getItem("theme"));
    this.selectedTheme = this.themeService.theme;
    this.selectedTheme.subscribe(data => {
      const overlayContainerClasses = this.overlayContainer.getContainerElement()
        .classList;
      const themeClassesToRemove = Array.from(
        overlayContainerClasses
      ).filter((item: string) => item.includes("-theme"));
      if (themeClassesToRemove.length) {
        overlayContainerClasses.remove(...themeClassesToRemove);
      }
      overlayContainerClasses.add(data);
    });
  }

So what is the best approach to get it done?

1

1 Answers

1
votes

I had issues with the background color as well when switching between a dark and light theme, because it was not sufficient to change the CSS class on the OverlayContainer, I had to change the CSS class on the body element as well.

Here the code that worked for me:

(you could find a full working code example at https://github.com/toongeorges/angular-electron-material-design/commit/4d91f9c21ed24b853da8284099e641676d620826)

  • in source/index.html:
<body class="mat-app-background">
  <app-root>Loading...</app-root>
</body>
  • in src/styles.scss:
//default theme
@include angular-material-theme($dark-theme);

.light-theme {
    @include angular-material-theme($light-theme);
}

.dark-theme {
    @include angular-material-theme($dark-theme);
}
  • in src/app/app.component.html:
    <button mat-raised-button color="accent" mat-button [matMenuTriggerFor]="menu" aria-label="Select Theme">
        Select Theme
    </button>
    <mat-menu #menu="matMenu">
        <button mat-menu-item (click)="onSetTheme('dark-theme')">
            <mat-icon svgIcon="brightness-2"></mat-icon>
            <span>Dark Theme</span>
        </button>
        <button mat-menu-item (click)="onSetTheme('light-theme')">
            <mat-icon svgIcon="brightness-7"></mat-icon>
            <span>Light Theme</span>
        </button>
    </mat-menu>
  • in src/app/app.component.ts:
  onSetTheme(theme: string) {
    if (theme === this.componentCssClass) {
      //ignore change
    } else {
      if (theme == 'dark-theme') {
        this.resetTheme(theme);
      } else if (theme == 'light-theme') {
        this.resetTheme(theme);
      } else {
        console.error("Unknown theme: " + theme);
      }
    }
  }

  resetTheme(theme: string) {
    const body = document.getElementsByTagName('body')[0];

    if (this.componentCssClass) {
      //remove the old style
      body.classList.remove(this.componentCssClass);
      this.overlayContainer.getContainerElement().classList.remove(this.componentCssClass);
    }

    this.componentCssClass = theme;
    //set the new style
    body.classList.add(this.componentCssClass);
    this.overlayContainer.getContainerElement().classList.add(this.componentCssClass);
  }