Angular 4 CLI, WebPack, dynamic permutation of the bootstrap theme for the entire website

I want to provide users with a button to change the theme of the entire website. I use ".scss" boot files for everything. Here is what I did:

I have "dark-styles.scss" and "light-styles.scss" in the "src / styles" folder. Both of these files override the classes and methods that I need to override, as well as import "bootstrap.scss" from the "node-module" for the default values. When I provide any of these files to the application through ".angular-cli.json", as shown below; It works great.

"styles": [ "../node_modules/font-awesome/css/font-awesome.css", "../node_modules/@swimlane/ngx-datatable/release/index.css", "../node_modules/@swimlane/ngx-datatable/release/assets/icons.css", "../src/styles/dark-styles.scss" ], 

or,

 "styles": [ "../node_modules/font-awesome/css/font-awesome.css", "../node_modules/@swimlane/ngx-datatable/release/index.css", "../node_modules/@swimlane/ngx-datatable/release/assets/icons.css", "../src/styles/light-styles.scss" ], 

If I provide a dark theme, dark, and if I provide a light, the theme is light.

But what I want to achieve dynamically allows users to change the theme. Hence, based on other answers in stackoverflow; I accessed the β€œdocument” in my application component, which is also my root component. This gives me access to the entire html page where I have a link tag that I can install from the component application.

HTML file

 <head> <link id="theme" type="text/scss" rel="stylesheet" src=""> </head> <body> content ..... </body> 

Angular-cli.json

 "styles": [ "../node_modules/font-awesome/css/font-awesome.css", "../node_modules/@swimlane/ngx-datatable/release/index.css", "../node_modules/@swimlane/ngx-datatable/release/assets/icons.css" ], 

App component:

 import { Component, OnInit, Inject } from '@angular/core'; import { DOCUMENT } from '@angular/platform-browser'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnInit { currentTheme: string; constructor( @Inject(DOCUMENT) private document) { } ngOnInit() { this.currentTheme = 'dark'; this.document.getElementById('theme').href = '../styles/dark-styles.scss'; } handelChangeTheme(event) { if (this.currentTheme === 'dark') { this.document.getElementById('theme').href = '../styles/light-styles.scss'; this.currentTheme = 'light'; console.log('light'); } else { this.document.getElementById('theme').href = '../styles/dark-styles.scss'; this.currentTheme = 'dark'; console.log('dark'); } } } 

When the "handleChangeTheme" event is fired, the href for #theme changes in the html file. But it does not update or apply styles. I understand that it has something to do with WebPack and how it compiles scss files. Has anyone encountered a similar situation or knew a solution to this problem. Thanks

+7
angular sass twitter-bootstrap webpack angular-cli
source share
2 answers

I just made your example locally and there seems to be a problem with type="text/scss" after I changed it to text/css , it starts working. At first I thought you needed to recreate the element, but the problem seems to be with the type

With his theme, I would recommend using compiled css versions of these files placed in the assets folder, and angular-cl will copy them to serve and build

Also, when you reference scss in your angular, it compiled from webpack to css.

+6
source share

I managed to get a dynamic theme running in Angular 4 + Bootstrap using the following approach:

The specific colors of the theme using the map:

 $themes: ( alpha: ( primary: #2b343e, info: #3589c7, top-color: #000000, top-font-color: #ffffff, ... ), beta: ( primary: #d2a444, info: #d2a444, top-color: #ffffff, top-font-color: #000000, ... ) ) 

Then, the following mixin was created to output colors for each theme name and set properties :

 @mixin theme($property, $key, $themes: $themes) { @each $theme, $colors in $themes { &.theme-#{$theme}, .theme-#{$theme} & { #{$property}: map-get($colors, $key); } } } 

I used mixins to manage individual properties:

 @mixin color($arguments...) { @include themify('color', $arguments...); } @mixin background-color($arguments...) { @include themify('background-color', $arguments...); } 

For each "thematic" component, I had to use the mixes above when declaring properties:

 .page-top { @include background-color('top-color'); @include color('top-font-color'); height: 66px; width: 100%; ... } 

The CSS output will look something like this:

 .page-top { height: 66px; width: 100%; ... } .page-top.theme-alpha, .theme-alpha .page-top { background-color: #000000; color: #ffffff; } .page-top.theme-beta, .theme-beta .page-top { background-color: #ffffff; color: #000000; } 

And finally, to make this theme accessible, you must control the theme class in some kind of parent component:

 <!-- class="theme-alpha" --> <main themeChange> <page-top></page-top> <sidebar></sidebar> <page-bottom></page-bottom> </main> 

The themeChange directive can be written as follows:

 @Directive({ selector: '[themeChange]' }) export class ThemeChange implements OnInit { @HostBinding('class') classes: string; private _classes: string[] = []; ngOnInit() { // grab the theme name from some config, variable or user input this.classesString = myConfig.theme; } } 
+1
source share

All Articles