Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 根据请求动态注入HTML和CSS_Javascript_Html_Css_Angular - Fatal编程技术网

Javascript 根据请求动态注入HTML和CSS

Javascript 根据请求动态注入HTML和CSS,javascript,html,css,angular,Javascript,Html,Css,Angular,所以我一直在研究如何从服务器加载CSS和HTML 我想要实现的是请求显示某个模板,该模板将HTML和CSS发送到网站,并将其与一些用户定义的样式(如颜色)一起加载 到目前为止,我能够使用以下方法注入HTML: <div [innerHTML]="template | sanitizeHtml"></div> 我在不同的帖子和博客上看到过(谢谢你) 我一直在构建的HTML非常有魅力: this.template = "<div clas

所以我一直在研究如何从服务器加载CSS和HTML

我想要实现的是请求显示某个模板,该模板将HTML和CSS发送到网站,并将其与一些用户定义的样式(如颜色)一起加载

到目前为止,我能够使用以下方法注入HTML:

<div [innerHTML]="template | sanitizeHtml"></div>
我在不同的帖子和博客上看到过(谢谢你)

我一直在构建的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>"
(对于那些想知道的人)

编辑2: 因此,我一直在研究如何使用这些模板:

用户可以注册多个设备,以显示office 365中的预订。用户可以通过两种方式设置模板,但这并不重要。当用户想要显示特定设备的模板时,他们会转到/device/:deviceid/template/:templateid。 这样,组件将加载到该设备的模板中。 因此,首先我们加载设备设置,其中包含模板的用户样式。然后,我们从office365加载必须显示在模板中的数据,最后使用模板样式加载模板。 因此,将有3个对服务器的请求。 设备设置--数据办公室365--模板

到目前为止,我已经能够加载数据并将其放入模板中,但模板在本地可用,而不是从服务器上可用。 我希望从服务器请求模板的原因是,将有一个管理门户,在那里制作和管理这些模板。
这些模板将有一个名称、HTML和CSS。

在经过清理的HTML中不使用
[ngStyle]
,而是只更改dom元素的类,其中插入了经过清理的HTML:

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

对于较大的模板差异,您可以使用Angular CDK Portal:

此处示例:

更新日期:2020年10月14日: 以前的解决方案要求包含编译器,这样您就无法在生产模式下构建项目。由于Owen Kelvins的回答,现在可以添加动态html和css,同时仍在生产中构建,因为它不需要编译器:

要添加自定义CSS,您可以使用Owen Kelvins方法或在html末尾附加“”标记,并将自定义CSS与end标记一起添加

原始答复: 我已经找到了这个问题的解决办法。多亏了discord服务器“Thecodingden”中的某个人,他给我发了消息,并给我一个指向Github的链接。翻阅这篇长文章后,我找到了答案。这就是我如何使用它来创建一个组件,该组件可以通过服务器请求基于给定id显示不同的模板,我还添加了一些注释来解释它

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

}
警告: 其中最重要的因素是,您不能以生产模式构建项目。这是因为JIT编译不起作用,您将得到以下错误:
这是因为angular编译器不包括在生产环境中,即使您尝试手动添加它。

仅为div添加类并使用scss/css文件添加样式不是更符合逻辑吗?当前模板不可读。此外,它还可以解决这个问题。您已经在使用style属性设置div的样式。同样的,你也使用了ngStyle。可能是因为这个,它没有被加载。@Billy Cottrell是的。我明白。但您可以只更改类名,并将所有样式代码存储在单独的css/scss文件中。它使代码更干净。而且拥有多个模板也没有问题。在这个项目中,我正在尝试的是现在有4个模板,但我可以很容易地添加新的模板。所以,我建议在您放入净化的InnerHtml的元素上使用NgClass。@Billy Cottrell如果仅基于用户设置,您只更改类,并且所有其他内容都存储在scss/css中,应用程序应该运行得很快。在这种情况下,您将拥有数百个特定于css的类。我将写一个我将如何做到这一点的答案。但是要知道模板也包含样式,还需要使用TrustStyles。不知道两者是否可以在同一个html上使用。但我认为不是。所以事情应该有所不同。好吧,我想我理解你的意思,但是ngClass在templateHtml变量中可以工作吗,我只是尝试在那里使用它,但似乎不起作用?因此在.ts文件中,如下所示:
this.templateHTML=“”这就是我需要在templateHtml内部应用样式的问题,如果样式表是从api下载的,那么我应该如何应用它?@Billy Cottrell试着看一下这个问题答案:门户设置看起来非常有趣,可能是一条路要走,我肯定会进一步研究这个问题。你能更新stackblitz链接吗?因为它似乎不起作用。我总是收到一个
无法获取/api/angular/v1
错误。谢谢你的帮助!如果我想使用门户,我需要为我想使用的每个模板制作一个组件。所以如果我有大约500个模板,我需要制作500个组件?那太疯狂了。我只希望像保存常规数据一样保存模板,并通过向服务器发出请求来获得某个模板。我猜Angular不支持从服务器请求加载模板。
@NgModule({
    declarations: [
        ...,
        SanitizeHtmlPipe
    ],
    ...
});
<div [ngClass]="templateClass" [innerHTML]="templateHtml"></div>
.template-class-1 {
    background-color: #f44336;
}
.template-class-2 {
    background-color: #4caf50;
}
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);
            });
    }

}
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 { }