Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 CLI, WebPack, switching bootstrap theme dynamically for the entire website

I want to provide users with a button to change the theme of the entire website. I am using bootstrap ".scss" files for everything. Here is what I have done:

I have "dark-styles.scss" and "light-styles.scss" in "src/styles" folder. Both of these files override the classes and methods that I need to override and also import the "bootstrap.scss" from "node-module" for the defaults. When I provide any of these file to the application through ".angular-cli.json" like below; it works perfectly.

"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 the dark the theme is dark and if I provide light the theme is light.

But what I want to achieve is dynamically allow the users to change the theme. Hence, based on other answers in stackoverflow; I accessed the "document" in my app component which is also my root component. It gives me access to the entire html page where I have a link tag which I can set from the app-component.

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');
        }
      }
    }

While triggering the event "handleChangeTheme" the href for the #theme changes in the html file. But it does not update or apply the styles. I understand that it has something to do with WebPack and the way it compiles the scss files. Has anybody faced the similar situation or know the solution to this issue. Thanks

like image 892
Virodh Avatar asked Jun 22 '17 17:06

Virodh


1 Answers

I just done your example locally and seems to be issue with type="text/scss" after i changed it to text/css it starts working. I thought firstly that you need to recreate element but issue seems to be with type

Since its theme i would recommend you to use compiled css versions of those files put them into assets folder and angular-cli will copy them on serve and build

In addition When you refer to scss in your angular its compiled with webpack to css.

like image 116
Vova Bilyachat Avatar answered Sep 22 '22 12:09

Vova Bilyachat