Skip to content Skip to sidebar Skip to footer

Angular 2 - How To Dynamically Change An Entire Css Stylesheet Based On Url Queryparams

I'm very new to the world of Angular (loving it so far). We have an Angular 1 (JS) app that we plan to convert to the latest Angular 2 (8.3.9) version. One thing that was done in

Solution 1:

After a lot of digging around, finally found the solution I was looking for. And it was so straight forward, hope this helps others that might be needing to do the same thing..

Get the css path from query params and then Inject the Document into a TS file... append the link to the head of the document.

I did this in a Router Guard using canActivate. I got the query param from the routerstatesnpshot like so:

Inject the DOCUMENT( don't forget the import) in the constructor

http://server.com/xxx&broker=1&client=2&css=http://cssServer.com/my_dynamic_stylesheet.css

import { DOCUMENT } from'@angular/common';

   @Inject(DOCUMENT) privatedocument: Documentthis.setDynamicStyle(state.root.queryParamMap.get('css'));

    setDynamicStyle(cssURL: string) {
        const head = this.document.getElementsByTagName('head')[0];
        const style = this.document.createElement('link');
        style.id = 'css-styling';
        style.rel = 'stylesheet';
        style.href = `${cssURL}`;
        head.appendChild(style);
    }

Thanks to: https://juristr.com/blog/2019/08/dynamically-load-css-angular-cli/

Solution 2:

This appears to be a fairly common issue, updating styling dynamically, and I can't find anything where people have attempted to override the entire CSS file/s for an Anuglar 2 app, post compilation.

What I ended up doing (for now)...

On GitHub link: https://github.com/angular/angular/issues/9343 Thanks to: peteboere

Created a directive like

import {Directive, ElementRef, Input} from'@angular/core';

@Directive({
    selector: '[cssProps]',
})
exportclassCSSPropsDirective {

    @Input() cssProps: any;

    constructor(private element: ElementRef) {}

    ngOnChanges({cssProps}) 
    {
        if (cssProps && cssProps.currentValue) 
        {
            const {style} = this.element.nativeElement;
            for (const [k, v] ofObject.entries(cssProps.currentValue)) 
            {
                style.setProperty(k, v);
            }
        }
    }
}

Which unfortunately means placing the cssProps on EACH and EVERY element in my documents that needs styling... like:

<div class="panel-heading" [cssProps]="cssStyling">

Then I created a simple Service to fetch styling in a JSON format like,

{--backgroundColor: "black"}

in the css file per component I used custom css properties, to handle these.

background: var(--backgroundColor)
    --backgroundColor: #008000;

NOTE TO SELF, doing this at app-root level, might mean not having to apply styles per component css file..., but we will still need to apply the directive to each element we want to style dynamically. ViewEncapsulation will need to be NONE across lower components.

Then, on an httpClient call every 10 seconds (for now) like:

import { HttpClient } from'@angular/common/http';
import { Subject, Subscription } from'rxjs';
import { Injectable } from'@angular/core';

@Injectable({providedIn: 'root'})
exportclassStyleSerivce {
    styleChanged = newSubject<any>();
    interval = newSubscription();

    styles:any;

    constructor(private httpClient: HttpClient) { }

    retrieveStyleFrom() {
         setInterval(() => {
            this.httpClient.get('https://serverName/stylesss.json')
            .subscribe(data => {
                console.log(data);
                this.styles = data;
                this.styleChanged.next(this.styles);
            })
         }, 10000);
    }
}

I subscribed to the styleChange in the respective components like:

this.styleSub = this.styleService.styleChanged.subscribe((styleNow) => {
      this.cssStyling = styleNow;
    })

and with cssStyling bound to my directive, as I update the DB where the JSON is stored, I can update the screen dynamically... (after the 10 second elapse)

This works, but the pain of setting this on each tag to make it dynamically updatable from DB/JSON updates is hectic.

I would not call this a solution to the initial problem, but a painful workaround.

Post a Comment for "Angular 2 - How To Dynamically Change An Entire Css Stylesheet Based On Url Queryparams"