Reputation: 91
I have angular wrapper module (app module) and many independent lazy-loaded sub-modules. Each sub-module behaves like a totaly separate app and needs its own angular material theme.
I've created custom theme for each sub-module and tried to reference the custom theme in each of components' .scss file with relative path.
Some of the Material components apply the custom theme (button) and some (mat-form-field) just take the theme specified in styles.scss.
One way I can avoid this is including each custom theme in 'styles' array of angular.json, but I'm afraid that, by doing this, each independent sub-module (app) will have to load every themes' compiled .css and it'll be overhead.
Is there any known issue with this or any better solution?
home-app.component.scss:
@import './theme.scss';
VS.
angular.json
...
"styles": [
"src/styles.scss",
"src/app/orgs/home/theme.scss" // <-- FIXED BY ADDING THIS
],
...
Expected: Theme declared in the home-app.component.scss will be loaded and applied to every material component used in home-app.component.html
Actual: If I don't add "src/app/orgs/home/theme.scss" to angular.json, the custom theme declared in styles.scss will be applied to some material components used in home-app.component.html, and some material components will use the imported theme specified in home-app.component.scss
Upvotes: 9
Views: 1415
Reputation: 3588
I think i understood your problem and here is a solution for you :)
So when you create a new ng-project with the cli with opt in material-theming, you will get a inital theming configuration like the following (or you can find the config in the Material Guides)
import '~@angular/material/theming';
// Plus imports for other components in your app.
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();
// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
// The warn palette is optional (defaults to red).
$candy-app-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($candy-app-theme);
The most important part of this is to remember that you must include just once the mat-core()
in your application (in order to have a single material styles css file).
After that you can create custtom themes by including import '~@angular/material/theming';
wherever desired in the application and apply the theme by wrapping it in a css calss. For example after you include the mat-core
once in you root .scss file, in a lazy loaded module you can do the following thing:
@import "~@angular/material/theming";
.theme1 {
$theme-primary: mat-palette($mat-red);
$theme-accent: mat-palette($mat-lime, A200, A100, A400);
// The warn palette is optional (defaults to red).
$theme-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$theme-theme: mat-light-theme($theme-primary, $theme-accent, $theme-warn);
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($theme-theme);
}
<div class="theme1">
<mat-toolbar color="accent">
<button color='primary' mat-button routerLink="/1">Go to 1</button>
<button color='primary' mat-button routerLink="/2">Go to 2</button>
</mat-toolbar>
</div>
Of course instead of two buttons you can also place your router-outlet inside the container with class theme1
and achive the desired result (different theme per lazy loaded module). Keep in mind that we are just importing import '~@angular/material/theming';` in the places where we need custom theming.
Here is a live example: CodeSandbox
Upvotes: 2
Reputation: 2685
Try to just add ng generate module Shared
which will create SharedModule at the root right next to AppModule with nothing in it. For some reason when it recompiles it may reconnect some of your sub modules to a theme like Angular Material Themes magically. Not sure what going on under the hood.
Upvotes: 0
Reputation: 1206
Did you try to add it directly into styles array of your Components?
@Component({
selector: 'app-home',
template: 'your-template.html',
styles: ['your-style.scss', 'your-theme.scss']
})
Another thing you can do is to use ShadowDom as your ViewEncapsulation :
@Component({
selector: 'app-home',
template: 'your-template.html',
styles: ['your-style.scss', 'your-theme.scss'],
encapsulation: ViewEncapsulation.ShadowDom
})
Upvotes: 4