Angular set component styleUrls dynamically

4.6k Views Asked by At

I am using the latest version of angualar 5.0 in the new project. And i am new to this framework and would appreciate some help from the angular developers.

I would like to set the styleUrls property with class level variable at the runtime dynamically. In my case, the styleURL path will be coming from the database via the angular service.

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

@Component({    
    templateUrl: './search.component.html',
    styleUrls: ['./search.component.css']
})


export class SearchComponent {
    pageName = 'New Search Page';
    PropfavMovie = 'Gladiator';

    constructor(private _titleSrv: Title) {
        this._titleSrv.setTitle('Search page');

    }

Is there a way i can set the Component's styleUrls property in the ngOnInit event or from the constructor of SearchComponent class.

In my case, every client has its own stylesheet. So that's i need to pull the stylesheet path from the db and populate the @components property dynamically.

2

There are 2 best solutions below

0
On BEST ANSWER

I'm not an expert but I don't think that what you're asking to do is possible given the way Angular works.

I believe the CSS pointed to by styleUrls, or the literal CSS provided in styles, is passed to the template compiler (called Ivy, in modern Angular) along with the component HTML. This makes a "component factory" which is used to make component instances at runtime. The factory can be compiled at build time (Ahead of Time / AOT) or dynamically on the client, but even in the latter case I think it is compiled when the owning module is initially loaded -- if it's possible to compile a new factory on the fly, I haven't seen any way to do it.

What I would suggest is making a separate module for each (type of) client, then looking up which module to use for that client and lazy-loading it with the Router. Alternately, maybe you can factor out the common parts of the various stylesheets into one static sheet, and make the rest of the style dynamic using ngClass conditionals.

5
On

You could use a function to dynamically calculate de style file to load:

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

//An alias that stores environment vars
import { ENV } from '@app/env';

//Function that calculates de css to load
export function getBrandCSS(styles: string[]): string [] {
    for(let i=0;i<styles.length;i++){
        styles[i] = './' + ENV.BRAND + '.' + styles[i];
    }
   return styles;
}

@Component({    
    templateUrl: './search.component.html',
    styleUrls: getBrandCSS(['search.component.css'])
})
export class SearchComponent {
    pageName = 'New Search Page';
    PropfavMovie = 'Gladiator';

    constructor(private _titleSrv: Title) {
        this._titleSrv.setTitle('Search page');
    }
}

This way you can have multiple css files named like this:

> brand1.search.component.css
> brand2.search.component.css
> brand3.search.component.css
> ***.search.component.css

They will be loaded based on an ENV var value. You could also edit the function to always load a base CSS and the specific one that overrides certains styles.