Angular 2 - Как динамически изменить всю таблицу стилей CSS на основе URL-параметров запроса - PullRequest
1 голос
/ 25 октября 2019

Я очень новичок в мире Angular (люблю его до сих пор). У нас есть приложение Angular 1 (JS), которое мы планируем конвертировать в последнюю версию Angular 2 (8.3.9). Одна вещь, которая была сделана в старом приложении, состояла в том, чтобы использовать объект $ scope, а затем динамически установить ссылку на таблицу стилей CSS в корневом index.html на основе параметра запроса в запрашивающем URL.

ИспользованиеngStyle или ngClass для обновления отдельных элементов в документе это круто, но,

Как мы справляемся с изменением всей таблицы стилей при загрузке приложения в Angular 2?

Все инкапсулировано внутри компонента, а стили, указанные в файле angular.json, встроены в файл deployable.js. Можно ли изменить его во время выполнения?

Эта ссылка является наиболее близким примером: Создание динамического CSS на основе угловых переменных , но все еще не решает проблему в корнефайл index.html.

Текущая старая версия

Url Arrives:

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

Параметр css-запроса извлекается в глобальную переменную и сохраняется в области видимости css_url, Inindex.html (начальная страница)

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

, и приложение начинает использовать любую таблицу стилей, которую предоставляет эта ссылка.

NEW Angular 2 (версия 8.3.9)

Мы хотим подражать описанному выше поведению, которого мы смогли достичь в версии JS. Извлеките URL-адрес из QueryParam, указывающий на некоторый файл CSS, и этот URL-адрес CSS можно вставить в основной файл index.html, чтобы изменить все стили приложений за один раз, или динамически получить доступ к таблице стилей в коде, чтобы обновить все за один раз.

Короче говоря, нам нужно 1 приложение, которое можно стилизовать с помощью CSS-файла на основе запроса.

Все мысли и комментарии будут высоко оценены.

Ответы [ 2 ]

1 голос
/ 14 ноября 2019

После долгих раскопок я наконец нашел решение, которое искал. И это было так просто, надеюсь, это поможет другим, которым, возможно, понадобится сделать то же самое.

Получить путь css из параметров запроса, а затем вставить документ в файл TS ... добавить ссылкув голову документа.

Я сделал это в Router Guard с помощью canActivate. Я получил параметр запроса от routerstatesnpshot следующим образом:

Внедрить ДОКУМЕНТ (не забудьте импортировать) в конструктор

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/

0 голосов
/ 30 октября 2019

Похоже, это довольно распространенная проблема, динамическое обновление стилей, и я не могу найти ничего там, где люди пытались переопределить весь файл CSS для приложения Anuglar 2, после компиляции.

То, что я в итоге делал (пока) ...

На ссылке 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;

ПРИМЕЧАНИЕ. SELF, делая это на уровне приложения, может означать, что не нужно применять стилидля каждого компонента css file ..., но нам все равно нужно будет применить директиву к каждому элементу, который мы хотим динамически стилизовать. ViewEncapsulation должен быть NONE для нижних компонентов.

Затем при вызове httpClient каждые 10 секунд (на данный момент), например:

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, является беспокойной.

Я бы не назвал это решением начальной проблемы, но болезненным обходным путем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...