3

For a given js variable, which has style information in it:

menuBgColor = "red";

In AngularJS I was able to use dynamically embedded style:

<div>
   <style>
      .menuElement{
         background-color:{{menuBgColor}}
      }
   </style>
   <div class="menuElement">...</div>
</div>

In Angular2+ I cannot use the same as above. When the view is rendered in the browser variable menuBgColor is not populated and the element is rendered as coded.

like this -

<body>
...other markup...
<div><style>.menuElement{background-color:{{menuBgColor}}}</style>
...markup...
</body>

I want to know that what are the other ways in angular 2+ to add dynamic styles to the view?

  • I know of ngStyle but the given example is a very small one.
  • In my case, I have to apply dynamic styles to each element of the whole app like button, borders, background, colors, tree controls, sidebars etc. So ngStyle is very exhaustive.
  • I also do not have predefined theme files because theme is managed by a feature in our app where user can define his/her own theme. Here I understand that I can refresh page to get the updated theme BUT consider that there can be 'n' number of users with their own themes.
  • So in my use case, the only solution I can think of is that somehow variable interpolate and create an embedded css.

Any help is greatly appreciated.

8
  • Is it menuBgColor or menu.bgColor? Commented Dec 18, 2017 at 12:04
  • Corrected, it is menuBgColor Commented Dec 18, 2017 at 12:07
  • What about CSS preprocessors like SASS/SCSS? Commented Dec 18, 2017 at 12:08
  • I also thought about css preprocessors but in my case, I have to update it runtime whereas sass -> css happens compile time. Commented Dec 18, 2017 at 12:10
  • change the style in head, ewoutreinders.com/index.php/… Commented Dec 18, 2017 at 12:13

2 Answers 2

2

You can try this:

<div [style.background-color]="yourVar"></div>

In this case the binding should work

Sign up to request clarification or add additional context in comments.

2 Comments

Good idea and I think this will work for many cases. But what if someone wants to set a style on a pseudo-element? Also the OP mentioned (and dismissed) ngStyle.
ok but there are many elements to style. It is exhaustive to add styles to around 1000 elements.
2

There's no pretty way to do this without building a huge structure like Angular Material does. But, if your theme system is not so complex, I'd simply go with a dynamically rendering of the <link> tag to your theme like so:

import { Component } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <link rel="stylesheet" [href]="getThemeUrl()">
    <div class="main">
        {{'themes/css/'+ theme +'.css' }}

        <select [(ngModel)]="theme" (change)="onThemeChanged(theme)">
            <option value="red">Red</option>
            <option value="blue">Blue</option>
            <option value="yellow">Yellow</option>
        </select>
    </div>
  `
})
export class AppComponent {
    theme = 'red';

    constructor(public sanitizer: DomSanitizer){}

    getThemeUrl(){
        return this.sanitizer
            .bypassSecurityTrustResourceUrl('themes/' + this.theme + '.css');
    }
}

Plunkr

5 Comments

It works perfectly, but only one problem with this is that the css file is re-requested on every UI interaction. Any way to avoid that?
@Ashwin maybe if you use [href]="'/themes/css/' + theme + '.min.css'"
Having a problem with running your problem. It keep on saying "Loading...". as soon as I fix it I will update you.
@Ashwin anyways there's a plunkr with a working solution embed.plnkr.co/lsi1VPHFaLSEoZraQcAF?p=preview it's a version mismatch try to compare angular's version in the system.config.js file.
I checked your plunkr and I am seeing one problem which I mentioned in my first comment i.e. when I have something else updating (like a variable interpolating) then the css file is requested again, if you could see that in Network tab. This gives a flickering UI on the screen. plnkr.co/edit/nV4WOR9efThiRs1V3gCK?p=preview

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.