load style file using bundleName in angular
Asked Answered
F

3

6

I have light and dark theme files and mentioned in angular.json file as below:

"styles": [
    "src/styles.scss",
    {
       "input": "src/styles/themes/light.theme.scss",
       "bundleName": "light-theme",
       "inject": false
    },
    {
       "input": "src/styles/themes/dark.theme.scss",
       "bundleName": "dark-theme",
       "inject": false
    }
],

and I want to inject each of the file dynamically via this code

loadStyle(styleName: string = 'light-theme' | 'dark-theme') {
  const head = this.document.getElementsByTagName('head')[0];

  let themeLink = this.document.getElementById('client-theme') as HTMLLinkElement;

  if (themeLink) {
    themeLink.href = styleName;
  } else {
    const style = this.document.createElement('link');
    style.id = 'client-theme';
    style.rel = 'stylesheet';
    style.href = `${styleName}`;

    head.appendChild(style);
  }
}

The above code creates link as

<link id="client-theme" rel="stylesheet" href="dark-theme"> // href="light-theme"

but nothing happens because the actual theme file is not being injected in the head-tag.

Update

Accoring to Angular Material docs

You can define multiple themes in separate files by creating multiple theme files per Defining a theme, adding each of the files to the styles of your angular.json. However, you must additionally set the inject option for each of these files to false in order to prevent all the theme files from being loaded at the same time. When setting this property to false, your application becomes responsible for manually loading the desired file. The approach for this loading depends on your application. https://material.angular.io/guide/theming#multiple-themes-across-separate-files

but the process of loading styles files in not there in the docs :(

Any suggestion/solution would be highly appreciable!!! :)

Fennel answered 8/2, 2022 at 8:10 Comment(0)
S
0

I don't think you can directly use the bundleName as href. Maybe try something like this:

style.href = `styles/themes/${styleName}.css`;
Summary answered 8/2, 2022 at 9:56 Comment(4)
Your solution is fine but there must be a use case for bundleName. In an article, the writer said to use the bundleName to call the style files but in my case it is not working.Fennel
It still uses bundleName since styleName is populated with dark-theme and not with dark.theme. I think it just replaces the file name and not the whole path and extension. Do you have a link to the article?Summary
here is the link juristr.com/blog/2019/08/dynamically-load-css-angular-cli if you get where I am missing please let me know.Fennel
It does seem to add the extension when toggling the theme: loadStyle('client-a.css'). The blog placed the files in the root folder which might explain why you need styles/themes as well..Summary
L
0

Set a default theme using inject attribute:

   {
       "input": "src/styles/themes/light.theme.scss",
       "bundleName": "light-theme",
       "inject": true
    },

or update your ngOnInit in AppComponent:

  ngOnInit(): void {
    this.loadStyle('light-theme');
  }
Loux answered 16/6, 2022 at 15:4 Comment(0)
K
0

let's talk about what inject,bundleName, input

  • [input] is a path where the scss/css files located

  • [inject: false] During development is common for dynamic theming

  • [inject: true] During development can inject a theme globally

  • bundleName is used for separate theme bundling and naming CSS files in production builds not in the development so no need to worry about bundleName in development we can put any name

angular.json File

{
                "input": "src/styles/themes/light-indigo.scss",
                "bundleName": "pr-light-indigo",
                "inject": false
}

HTML

 <link
      id="app-theme"
      rel="stylesheet"
      type="text/css"
      href="pr-light-indigo.css"
    />

here I create light-indigo.scss file under src/styles/theme path here bundle name is slightly different it's like pr-light-indigo.

When trying to run the project in development mode it doesn't check the bundleName which means the pr-light-indigo file returns a 404 status.

When trying to run the project in production it checks the bundleName pr-light-indigo that we already link in the HTML file so it returns a 200 ok status

So in you're case you have to modify your code like this

 style.href = `${styleName}.css`
Kylstra answered 5/2, 2024 at 10:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.