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 documentation site for the latest version of angular material [5.0.0-rc0]
I have two custom themes, this is custom-theme.scss and there is light-custom-theme.scss which is nearly identical, sans the mat-dark-theme
@import '~@angular/material/theming';
$custom-theme-primary: mat-palette($mat-blue);
$custom-theme-accent: mat-palette($mat-orange, A200, A100, A400);
$custom-theme-warn: mat-palette($mat-red);
$custom-theme: mat-dark-theme($custom-theme-primary, $custom-theme-accent, $custom-theme-warn);
@include angular-material-theme($custom-theme);
My styles.scss looks like so
@import '~@angular/material/theming';
@include mat-core();
@import 'custom-theme.scss';
@import 'light-custom-theme.scss';
.custom-theme {
@include angular-material-theme($custom-theme);
}
.light-custom-theme {
@include angular-material-theme($light-custom-theme);
}
And then it's called in the index.html <body class="mat-app-background">
Everything works fine when I do one theme. But I am trying to switch between the two. Adding both themes into angular-cli.json, the light-custom-theme takes over
"styles": [
"styles.scss",
"custom-theme.scss",
"light-custom-theme.scss"
],
I have the following code in place in one of my components to handle toggling themes
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.classList.remove("light-custom-theme");
this.overlay.classList.add("custom-theme");
} else {
this.overlay.classList.add("light-custom-theme");
}
}
But whenever it runs the theme remains the same. For what it is worth, there is already a "cdk-overlay-container" object at position 0 in overlay.classList
0:"cdk-overlay-container"
1:"custom-theme"
length:2
value:"cdk-overlay-container custom-theme"
I am unsure how to debug this as the angular material documentation doesn't give me too much to work with, any help would be appreciative!
Thanks!
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.
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
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
app.module.ts
Finally, call the onSetTheme function from your view.
app.component.html
You might consider using an observable so that the functionality would be more dynamic.
You have to use the
getContainerElement
method ofOverlayContainer
. Here's some example usage:As for your style files, I strongly suggest removing this line for both
custom-theme.scss
andlight-custom-theme.scss
(you only need it for your classes in this case):If you also want to toggle the theme for your app, you should probably use this in the same
toggleTheme
method: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.