J'ai lu quelques articles à ce sujet, mais ils semblent être en conflit de différentes manières. J'espère recréer le même thème que le site de documentation sur les matériaux angulaires pour la dernière version de matériel angulaire [5.0.0-rc0]
J'ai deux thèmes personnalisés, c'est custom-theme.scss et il y a light-custom-theme.scss qui est presque identique, sans le thème mat-dark
@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);
Mon styles.scss ressemble tellement
@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);
}
Et puis ça s'appelle dans le index.html <body class="mat-app-background">
Tout fonctionne bien quand je fais un thème. Mais j'essaie de basculer entre les deux. En ajoutant les deux thèmes dans angular-cli.json, le thème light-custom-reprend
"styles": [
"styles.scss",
"custom-theme.scss",
"light-custom-theme.scss"
],
J'ai le code suivant en place dans l'un de mes composants pour gérer les thèmes de basculement.
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");
}
}
Mais chaque fois qu'il fonctionne, le thème reste le même. Pour ce que cela vaut, il existe déjà un objet "cdk-overlay-container" à la position 0 dans overlay.classList
0:"cdk-overlay-container"
1:"custom-theme"
length:2
value:"cdk-overlay-container custom-theme"
Je ne suis pas sûr de savoir comment résoudre ce problème car la documentation matérielle angulaire ne me donne pas trop de travail, toute aide serait la bienvenue!
Merci!
Voici une solution alternative pour Angular 5.1 +/Angular Material 5.0+.
* Edit: Comme indiqué, cela fonctionne toujours dans Angular 7+.
Exemple éditable de travail - https://stackblitz.com/edit/dynamic-material-theming
Dans theme.scss, incluez un thème par défaut (notez qu'il n'est pas conservé sous un nom de classe; Angular l'utilisera donc par défaut), puis un thème clair et sombre.
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)
}
Dans le fichier app.component, incluez OverlayContainer à partir de @ angular/cdk/overlay. Vous pouvez trouver la documentation de Angular à ce sujet ici https://material.angular.io/guide/theming ; bien que leur mise en œuvre soit un peu différente. Veuillez noter que je devais également inclure OverlayModule en tant qu'import dans app.module.
Dans mon fichier app.component, j'ai également déclaré @HostBinding('class') componentCssClass;
en tant que variable, qui sera utilisée pour définir le thème en tant que classe.
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 {}
Enfin, appelez la fonction onSetTheme à partir de votre vue.
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>
Vous pouvez envisager d'utiliser un observable afin que la fonctionnalité soit plus dynamique.
Vous devez utiliser la méthode getContainerElement
de OverlayContainer
. Voici quelques exemples d'utilisation:
this.overlay.getContainerElement().classList.add('my-theme');
En ce qui concerne vos fichiers de style, je vous suggère fortement de supprimer cette ligne à la fois pour custom-theme.scss
et light-custom-theme.scss
(vous n’en aurez besoin que pour vos classes):
@include angular-material-theme($custom-theme); // Remove this line from custom-theme.scss and light-custom-theme.scss
Si vous souhaitez également basculer le thème de votre application, vous devez probablement l’utiliser dans la même méthode toggleTheme
:
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");
}
}
Vous pouvez toujours vérifier comment le sélecteur de thème est implémenté dans https://material.angular.io/ et faire de même https://github.com/angular/material.angular.io/tree/master/src/app/shared/theme-picker vous disposerez ainsi de la solution permanente, au cas où des changements radicaux pourraient toujours être recherchés dans la source de la documentation correspondante.