How to change the ng-zorro theme at runtime

Viewed 3175

I did a lot of research, and couldn't find a way to generate the ng-zorro themes and change it on the runtime.

Finally, I could find a way to do this.

2 Answers

Demo: https://ashotaleqs.github.io/ng-zorro-switch-theme/

  1. At first you need to install less-plugin-clean-css dev dependency by command npm i less -D less-plugin-clean-css -D

  2. Create themes folder in assets folder

  3. Define less-compiler.js which contains:

const less = require('less');
const LessPluginCleanCSS = require('less-plugin-clean-css');
const fs = require('fs');

// ng zorro defined styles
const basicStyles = `@import './node_modules/ng-zorro-antd/ng-zorro-antd.less';`;
// ng zorro compact theme variables
const compactThemeVars = require('ng-zorro-antd/compact-theme');
// ng zorro dark theme variables
const darkThemeVars = require('ng-zorro-antd/dark-theme');

less.render(`${basicStyles}`, {
  javascriptEnabled: true,
  plugins: [new LessPluginCleanCSS({ advanced: true })],
  modifyVars: {

    ...compactThemeVars,
    ...{
      // for the compact theme
      // you need to add your color variables here
      // you can find the full variables list here
      // https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/scripts/site/_site/doc/theme.less
      'primary-color': '#111521',
      'error-color': 'green'
    }
  }
}).then(data => {
  fs.writeFileSync(
    // output path for the theme style
    './src/assets/themes/compact.css',
    data.css
  )
}).catch(e => {
  // log the render error
  console.error(e);
});

less.render(`${basicStyles}`, {
  javascriptEnabled: true,
  plugins: [new LessPluginCleanCSS({ advanced: true })],
  modifyVars: {
    ...darkThemeVars,
    ...{
      // for the dark theme
      // you need to add your color variables here
      // you can find the full variables list here
      // https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/scripts/site/_site/doc/theme.less
      'primary-color': '#02cadb',
      'error-color': 'yellow'
    }
  }
}).then(data => {
  fs.writeFileSync(
    // output path for the theme style
    './src/assets/themes/dark.css',
    data.css
  )
}).catch(e => {
  // log the render error
  console.error(e);
});

here is the link of the full variables less variables

  1. Run node ./less-compiler.js in the terminal (this command should generate the dark.css and compact.css files in the src/assets/themes folder)

  2. (optional) If you want to run node ./less-compiler.js every time when you build the project, you can replace "build": "ng build", with "build": "ng build && node ./less-compiler.js", in package.json and after you can build your project by npm run build command.

  3. add <link rel="stylesheet" id="theme-link" href="/assets/themes/compact.css"> into the head of your index.html file.

  4. Define a function that helps you remove or add the link of the theme into the head. (In my case the function defined in the app.component.ts file)

// ..........................
export class AppComponent {
  theme = '';
  constructor() {
      setInterval(() => {
         this.changeTheme()
      }, 2000);
  }

  changeTheme() {
    this.theme = this.theme === 'dark' ? '' : 'dark';
    const style = document.getElementById('theme-link') as HTMLLinkElement;
    if (this.theme === 'dark') {
      style.href = '/assets/themes/dark.css';
    } else {
      style.href = '/assets/themes/compact.css';
    }
  }
}

I hope this can help you easily organize the runtime theme switching.

and also here is the link of the simple project repository

GitHub Repository

The easier way could be just to create two theme files e.g. theme-default.less and theme-dark.less. default theme imports default ng-zorro styles and the dark theme imports dark ng-zorro styles. include them both in the assets section of angular.json. You just need to scope the dark styles under some class or something for them to applied conditionally. like this:

theme-default.less:

@import '~ng-zorro-antd/ng-zorro-antd.dark.less';
// default vars
@primary-color: #3f87f5;

theme-dark.less:

body.dark {
  @import '~ng-zorro-antd/ng-zorro-antd.dark.less';
  // dark vars
  @primary-color: #3f87f5;
}

Now you just have to apply the .dark class to the body to change the theme to dark.

Related