Динамически вводить HTML и CSS по запросу - PullRequest
2 голосов
/ 24 февраля 2020

Итак, я искал, как загрузить CSS и HTML с сервера.

Чего я хочу добиться - это запросить отображение определенного шаблона, который отправляет HTML и CSS на веб-сайт и загружает его вместе с некоторыми пользовательскими стилями, такими как цвет

. До сих пор я мог вводить HTML, используя:

<div [innerHTML]="template | sanitizeHtml"></div>

и

import { Pipe, PipeTransform, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
    name: 'sanitizeHtml'
})
export class SanitizeHtmlPipe implements PipeTransform {

    constructor(private sanitizer: DomSanitizer) { }
    transform(value: any): any {
        return this.sanitizer.bypassSecurityTrustHtml(value);
    }

}

Что я видел в разных постах и ​​блогах (спасибо вам за это).

HTML Я строил работы как шарм:

this.template = "<div class='template' style='width: 1080px; height: 1920px; background-color: #212121;'><div class='clr-row' style='padding:45px 0px 10px 25px; position: relative; width: inherit;'><div class='clr-col-5'><div style='width: 230px; height: 60px; background-image: url(*LINK_TO_IMAGE*); background-repeat: no-repeat; float: left;'></div></div></div></div>"

Этот HTML является частью полного шаблона. Итак, я хотел бы использовать стили с помощью переменных.

Итак, я попытался создать объект стиля:

public style: {};
public template: string;
ngOnInit(){
    this.style = {
        template: {
            "color": "#D8B088",
        }
    }
    this.template = "<div [ngStyle]='style.template' class='template' style='width: 1080px; height: 1920px; background-color: #212121;'><div class='clr-row' style='padding:45px 0px 10px 25px; position: relative; width: inherit;'><div class='clr-col-5'><div style='width: 230px; height: 60px; background-image: url(*LINK_TO_IMAGE*); background-repeat: no-repeat; float: left;'></div></div></div></div>"
}

Я добавил объект стиля в шаблон с помощью [ngStyle] = 'style.template', по какой-то причине стиль не был загружен, поэтому я попытался использовать вместо него camelCasing, но все равно безуспешно.

Так кто-то знает, как заставить CSS работать в этом случае и в конечном итоге использовать пользовательские стили?

Заранее спасибо.

Редактировать 1:

Я также включил Sanitize труба в app.module.ts:

@NgModule({
    declarations: [
        ...,
        SanitizeHtmlPipe
    ],
    ...
});

(для тех, кому было интересно)

Edit 2:

Так что я работаю над тем, чего я хочу иметь с этими шаблонами:

Пользователь может зарегистрировать несколько устройств там, где они хотят отображать заказы из офиса 365. Пользователь может настроить шаблоны двумя способами, но это не имеет значения. Когда пользователь хочет отобразить шаблон для определенного устройства, он go отправляет / device /: deviceid / template /: templateid. Таким образом, компонент будет загружен в шаблон этого устройства. Итак, сначала мы загружаем в настройках устройства, которые содержат пользовательские стили для шаблона. После этого мы загружаем данные из office365, которые должны отображаться в шаблоне, и, наконец, загружаем в шаблон стили шаблона. Таким образом, будет 3 запроса к серверу. DeviceSettings - Data Office365 - Шаблон

До сих пор я был в состоянии загрузить данные и поместить их в шаблон, но шаблон был доступен локально, а не с сервера. Причина, по которой я хочу, чтобы шаблоны запрашивались с сервера, заключается в том, что будет административный портал, где эти шаблоны будут создаваться и управляться. Эти шаблоны будут иметь имя, HTML и CSS.

Ответы [ 3 ]

1 голос
/ 24 февраля 2020

Для больших различий в шаблонах вы можете использовать Angular CDK Portal: https://material.angular.io/cdk/portal/overview

Пример здесь: https://stackblitz.com/angular/mkvvyvgqxox?file=src%2Fapp%2Fcdk-portal-overview-example.ts

0 голосов
/ 10 марта 2020

Я нашел решение этой темы. Благодаря кому-то на сервере разногласий "The Coding Den" он сообщил мне об этом и дал ссылку на Динамически загружаемый шаблон для компонента на Github. Пролистав этот длинный пост, я нашел ответ Alarm9k . Вот как я использовал его для создания компонента, который мог бы отображать различные шаблоны на основе заданного идентификатора через запрос к серверу. Я также добавил несколько комментариев, чтобы объяснить это.

import { Component, AfterViewInit, Compiler, NgModule, ViewChild, ViewContainerRef, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BookingService } from 'src/app/services/booking.service';
import { ApplicationModel } from 'src/app/models/application.model';
import { Booking } from 'src/app/models/vo/booking';
import { Subscription } from 'rxjs';
import { SplitStringPipe } from '../../utils/split-string.pipe';
import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BrowserModule } from '@angular/platform-browser';

@Component({
    selector: 'app-bookings-template',
    templateUrl: './bookings-template.component.html',
    styleUrls: ['./bookings-template.component.css']
})
export class BookingsTemplateComponent implements AfterViewInit {

    public template: string;
    public date: Date;
    public locale: string;
    public id: string;

    @ViewChild('container', { read: ViewContainerRef, static: false }) container: ViewContainerRef;

    constructor(private compiler: Compiler, private bs: BookingService, private apm: ApplicationModel) { }

    ngAfterViewInit() {
        // Must clear cache.
        this.compiler.clearCache();
        // fill in template from server request
        this.template = "<div class="test">{{test}}</div>;
        var styles = ".test{color:red}";
        // Define the component using Component decorator.
        const component = Component({
            template: this.template + "<div>Hard Coded html for error checks and loading spinner</div>",
            styles: [styles]
        })(class implements OnInit {
            //example properties
            public date: Date;
            public bookings: Array<Booking>;
            public isLoading: boolean = true;
            public hasError: boolean = false;
            public errorMessage: string;
            public errorMessageSub: Subscription;
            public bs: BookingService;
            public apm: ApplicationModel;
            // Do not pass any parameters in the constructor or it will break!
            // Instead pass it within the factory method down below as a property!
            constructor() {
                // refresh template every minute
                setInterval(() => {
                    this.ngOnInit();
                }, 60000);
                // refresh date every second
                setInterval(() => {
                    this.date = new Date();
                }, 1000);
            }

            ngOnInit() {
                // get data to fill in template
            }
            ngOnDestroy() {
                //remove error subscription
                this.errorMessageSub.unsubscribe();
            }
        });

        // Define the module using NgModule decorator.
        //Modules can be changed based on your needs
        const module = NgModule({
            imports: [
                CommonModule,
                BrowserAnimationsModule,
                BrowserModule,
                HttpClientModule],
            declarations: [component, SplitStringPipe],
            providers: [BookingService]
        })(class { });

        // Asynchronously (recommended) compile the module and the component.
        this.compiler.compileModuleAndAllComponentsAsync(module)
            .then(factories => {
                // Get the component factory.
                const componentFactory = factories.componentFactories[0];
                // Create the component and add to the view.
                const componentRef = this.container.createComponent(componentFactory);
                // pass parameters that would go in the constructor as properties
                // subscriptions should also work.
                componentRef.instance.bs = this.bs;
                componentRef.instance.apm = this.apm;
                componentRef.instance.errorMessageSub = this.apm.getMessageError().subscribe(me => componentRef.instance.errorMessage = me);
            });
    }

}

BookingsTemplateComponent действует как родительский класса анонимного компонента, который действует как дочерний. Таким образом, дочерний элемент может быть добавлен к родителю благодаря @ViewChild, где указано имя контейнера и совпадает с родительским html id: <div #container></div> (в данном случае).

Вам также потребуется добавьте некоторые вещи в модуль приложения:

import { NgModule, CompilerFactory, Compiler, COMPILER_OPTIONS } from '@angular/core';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';
import { CommonModule } from '@angular/common';

export function createCompiler(compilerFactory: CompilerFactory) {
    return compilerFactory.createCompiler();
}
@NgModule({
    declarations: [
        // components and pipes
        ...
    ],
    imports: [
        CommonModule, // required
        ... //other modules
    ],
    providers: [
        // different services
        ...,
        // these are need to add the compiler manually to the project
        { provide: COMPILER_OPTIONS, useValue: {}, multi: true },
        { provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
        { provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

ПРЕДУПРЕЖДЕНИЕ:

Самый важный фактор этого заключается в том, что вы не можете построить проект в рабочем режиме. Причина этого в том, что JIT-компиляция не работает, и вы получите следующую ошибку: Angular JIT compilation failed: '@angular/compiler' not loaded Это связано с тем, что компилятор angular не включен в производственную среду, даже когда вы пытаетесь добавьте его вручную.

0 голосов
/ 24 февраля 2020

Вместо использования [ngStyle] в sanitized HTML, я бы вместо этого просто изменил класс для элемента dom, в который вставляется sanitized HTML:

<div [ngClass]="templateClass" [innerHTML]="templateHtml"></div>

Таким образом, код более читабелен и код стиля отделен от HTML.

Css для шаблонов будет выглядеть так:

.template-class-1 {
    background-color: #f44336;
}
.template-class-2 {
    background-color: #4caf50;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...