I'm writing an angular 12 website with angular material. This project supports several domains and on different domains it supposed to show different theme.
so what I'm trying to resolve here is to be able to load themes dynamically with lazy loading.
my custom theme works.. basic angular material functionality doesn't, and I do get the message
Could not find Angular Material core theme. Most Material components may not work as expected. For more info refer to the theming guide: https://material.angular.io/guide/theming
I googled a lot and if I load the css file properly and append it to the head, it should work properly.
ok.. so first..
I created app/themes directory
I have 3 themes, windy.scss
, windy-car.scss
, and windy-shop.scss
, each one of them requires common.scss
.
i have several components that uses variables that I created in each file with specific color, and the common.scss actually decorate the components when the chosen colors.
for example:
common.js
includes:
app-root {
div#my-mat-drawer {
background: $container-bg;
}
}
and windy.scss
contains:
$container-bg: #aabbcc;
i'll show one scss file as an example, when i used just one theme it worked so i know the format is good.
this is windy.scss
:
@use '../../node_modules/@angular/material/index' as mat;
$container-bg: #aabbcc;
$container-color: white;
$button1-color: #ccdd99;
$button2-color: #112233;
$product-card-text: red;
$category-title-bg: blue;
$product-categories-bg: yellow;
$toolbar-bg-color: green;
$dark-primary-text: rgba(black, 0.87);
$dark-secondary-text: rgba(black, 0.54);
$dark-disabled-text: rgba(black, 0.38);
$dark-dividers: rgba(black, 0.12);
$dark-focused: rgba(black, 0.12);
$light-primary-text: white;
$light-secondary-text: rgba(white, 0.7);
$light-disabled-text: rgba(white, 0.5);
$light-dividers: rgba(white, 0.12);
$light-focused: rgba(white, 0.12);
$my-cyan-palette: (
50: #e0f7fa,
100: #b2ebf2,
200: #80deea,
300: #4dd0e1,
400: #26c6da,
500: #00bcd4,
600: #00acc1,
700: #0097a7,
800: #00838f,
900: $button2-color,
A100: #84ffff,
A200: #18ffff,
A400: #00e5ff,
A700: #00b8d4,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $dark-primary-text,
400: $dark-primary-text,
500: $light-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
A100: $dark-primary-text,
A200: $dark-primary-text,
A400: $dark-primary-text,
A700: $dark-primary-text,
)
);
$my-lime-palette: (
50: #f9fbe7,
100: #f0f4c3,
200: #e6ee9c,
300: #dce775,
400: #d4e157,
500: #cddc39,
600: #c0ca33,
700: #afb42b,
800: #9e9d24,
900: $button1-color,
A100: #f4ff81,
A200: #eeff41,
A400: #c6ff00,
A700: #aeea00,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $dark-primary-text,
400: $dark-primary-text,
500: $dark-primary-text,
600: $dark-primary-text,
700: $dark-primary-text,
800: $dark-primary-text,
900: $light-primary-text,
A100: $dark-primary-text,
A200: $dark-primary-text,
A400: $dark-primary-text,
A700: $dark-primary-text,
)
);
$windy-store-primary: mat.define-palette($my-cyan-palette, 900);
$windy-store-accent: mat.define-palette($my-lime-palette,900);
$windy-store-warn: mat.define-palette($my-cyan-palette,900);
$windy-store-theme: mat.define-light-theme((
color: (
primary: $windy-store-primary,
accent: $windy-store-accent,
warn: $windy-store-warn,
)
));
@include mat.all-component-themes($windy-store-theme);
@import "common";
now.. in angular.json i added these files with inject: false
:
"styles": [
"src/styles.scss",
{
"input": "src/themes/windy.scss",
"bundleName": "windy",
"inject": false
},
{
"input": "src/themes/windy-car.scss",
"bundleName": "windy-car",
"inject": false
},
{
"input": "src/themes/windy-shop.scss",
"bundleName": "windy-shop",
"inject": false
}
]
I created a style-manager service and a theme.service and added them to the provider in app.module.ts
.
style-manager-service.ts
/**
* Copied from https://github.com/angular/material.angular.io/blob/master/src/app/shared/style-manager/style-manager.ts
*/
import { Injectable } from "@angular/core";
@Injectable()
export class StyleManagerService {
constructor() {}
/**
* Set the stylesheet with the specified key.
*/
setStyle(key: string, href: string) {
getLinkElementForKey(key).setAttribute("href", href);
}
/**
* Remove the stylesheet with the specified key.
*/
removeStyle(key: string) {
const existingLinkElement = getExistingLinkElementByKey(key);
if (existingLinkElement) {
document.head.removeChild(existingLinkElement);
}
}
}
function getLinkElementForKey(key: string) {
return getExistingLinkElementByKey(key) || createLinkElementWithKey(key);
}
function getExistingLinkElementByKey(key: string) {
return document.head.querySelector(
`link[rel="stylesheet"].${getClassNameForKey(key)}`
);
}
function createLinkElementWithKey(key: string) {
const linkEl = document.createElement("link");
linkEl.setAttribute("rel", "stylesheet");
linkEl.setAttribute("type", "text/css");
linkEl.classList.add(getClassNameForKey(key));
document.head.appendChild(linkEl);
return linkEl;
}
function getClassNameForKey(key: string) {
return `app-${key}`;
}
and theme.service.ts
import { Injectable } from "@angular/core";
import { StyleManagerService } from "./style-manager.service";
@Injectable()
export class ThemeService {
constructor(
private styleManager: StyleManagerService
) {}
setTheme(themeToSet: string) {
this.styleManager.setStyle(
"theme",
`${themeToSet}.css`
);
}
}
and I injected private readonly themeService: ThemeService
in app.component.ts
and ran this.themeService.setTheme('windy-car');
in the constructor.
and the results.. i do see the custom colors for the chosen theme, but angular material functionality is broken. color=primary
doesn't work and other related styles to angular material do not show.
for example in the toolbar i have color="primary"
and still the color is white.
I'm sure it's related to the error Could not find Angular Material core theme. Most Material components may not work as expected. For more info refer to the theming guide: https://material.angular.io/guide/theming
but I have no idea how to resolve this.
any ideas ?
** update 1 **
when i added the following in styles.scss
:
@import '~@angular/material/theming';
@include mat-core();
i still get the error
Could not find Angular Material core theme. Most Material components may not work as expected. For more info refer to the theming guide: https://material.angular.io/guide/theming
angular material components work properly but it ignores my chosen colors completely.