Angular 2 - 如何根据URL查询参数动态更改整个CSS样式表

8
我对Angular的世界非常陌生(但至今很喜欢它)。我们有一个Angular 1(JS)应用程序,计划将其转换为最新的Angular 2(8.3.9)版本。旧应用程序中使用了$scope对象,并根据请求URL中的查询参数动态设置根index.html中的CSS样式表链接。

使用ngStyle或ngClass更新文档中的单个元素很酷,但是:

在Angular 2中如何处理加载应用程序时更改整个样式表?

一切都封装在组件内部,angular.json文件中指定的样式被构建到“deployable.js”文件中。是否可能在运行时进行更改?

此链接似乎是最接近的示例:Generate dynamic css based on variables angular,但仍未解决根index.html文件的问题。

当前的OLD版本:

URL到达:

http://someserver:port/app?css=http://linktoCSs/cssFile.css

将css查询参数拉入全局变量,并将其存储在名为css_url的作用域上,在index.html(起始页面)。

<link rel="stylesheet" ng-href="{{css_url}}">

应用程序将使用链接提供的样式表进行开始。

全新的Angular 2(版本8.3.9)

我们想要模仿在JS版本中实现的上述行为。从QueryParam中获取指向某个CSS文件的URL,可以将该CSS URL注入到主index.html中以一次性更改整个应用程序的样式,或者在代码中动态访问样式表以一次性更新所有内容。

简而言之,我们希望一个应用程序可以通过基于QueryParam的CSS文件进行样式设置。

非常感谢所有的想法和评论。


也许这会有帮助:https://coryrylan.com/blog/build-css-themes-with-css-custom-properties-and-sass - Chellappan வ
会检查一下,谢谢 Chellappan。 - CraigSS
我已经检查过了,不幸的是它并没有解决手头的问题...肯定有其他方法可以做到这一点吧? - CraigSS
我还没有遇到过这种要求,抱歉。 - Chellappan வ
嗨@Chellappan,你看到解决方案了吗?如果你有任何意见,请告诉我。 - CraigSS
一定会尝试回答这个问题的~! - Chellappan வ
2个回答

12

经过一番搜索,终于找到了我要寻找的解决方案。 而且它非常简单明了,希望这能帮助需要做同样事情的其他人..

从查询参数中获取 CSS 路径,然后将 Document 注入到 TS 文件中... 将链接附加到文档头部。

我在 Router Guard 中使用 canActivate 来完成这个操作。 我从路由器状态快照中获取查询参数的方法如下:

在构造函数中注入 DOCUMENT(不要忘记导入)

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

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

   @Inject(DOCUMENT) private document: Document

   this.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);
    }

感谢: https://juristr.com/blog/2019/08/dynamically-load-css-angular-cli/


1
这似乎是一个相当常见的问题,即在运行时动态地更新样式,并且我无法找到任何关于在编译后尝试覆盖整个 Angular 2 应用程序的 CSS 文件的内容。
我最终所做的(目前)是...
在 GitHub 链接中:https://github.com/angular/angular/issues/9343 感谢:peteboere 创建了一个类似指令的东西。
import {Directive, ElementRef, Input} from '@angular/core';

@Directive({
    selector: '[cssProps]',
})
export class CSSPropsDirective {

    @Input() cssProps: any;

    constructor(private element: ElementRef) {}

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

“不幸的是,这意味着在需要进行样式设置的每个元素上都要放置cssProps,例如:”
<div class="panel-heading" [cssProps]="cssStyling">

然后我创建了一个简单的服务,以JSON格式获取样式,例如:

{--backgroundColor: "black"}

在每个组件的CSS文件中,我使用了自定义CSS属性来处理它们。
    background: var(--backgroundColor)
    --backgroundColor: #008000;

注意,如果在应用程序根级别执行此操作,则可能不需要针对每个组件CSS文件应用样式,但仍需要将指令应用于要动态设置样式的每个元素。在较低的组件中,ViewEncapsulation将需要设置为NONE。

然后,每10秒钟(目前)进行一次httpClient调用,如下:

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

@Injectable({providedIn: 'root'})
export class StyleSerivce {
    styleChanged = new Subject<any>();
    interval = new Subscription();

    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);
    }
}

我在相关组件中订阅了styleChange事件,如下所示:

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

通过将cssStyling绑定到我的指令上,当我更新存储JSON的数据库时,我可以动态地更新屏幕...(在10秒后)

这个方法是可行的,但是在每个标签上设置它以使其能够从DB / JSON更新中进行动态更新的痛苦是繁琐的。

我不会把这称为解决初始问题的方法,而是一个痛苦的解决方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接