加载外部模板

时间:2019-09-02 19:21:49

标签: angular

我遇到以下问题:

我必须将外部模板加载到我的Angular应用中

这些模板的网址存储在数据库中

有一个用于以下目的的模板URL:

  • 标题
  • 正文(包含Content div)
  • 页脚

主体模板包含一个

<div id="content"></div>

将具有ID的ID放入此div,应该加载我的Apps Angular Content。

我当前的方法:

在我的AppComponent onInit中,我正在从数据库加载Urls,并通过另一个http GET调用来检索这些URL。 我正在显示微调框,直到所有内容加载完毕。

我发现有关加载外部模板的唯一一件事是[innerHTML]和DomSanitizers bypassSecurity一起加载模板,然后在我的组件中使用ID选择器

<html>
  <ng-container [innerHTML]='header | safeHtml'>
  <ng-container [innerHTML]='body | safeHtml'>
  <ng-container [innerHTML]='footer | safeHtml'>
</html>

然后我的组件将通过ID选择器插入其内容

@Component({ selector: '[id=content]', })

这是一种工作方式,但是您可以想象,它不是非常有效,并且可能不是最佳方法。而且选择器不起作用,我的组件不在模板的div之内

还有其他方法可以实现这种情况吗?

当前,使用index.jsp导入这些模板,现在另一个想法是将我angular.json中的index.html更改为单独的index.jsp,以简化构建过程,但问题是开发过程中缺少该文件,因为webpack无法处理.jsp文件。

2 个答案:

答案 0 :(得分:0)

我想到的唯一可能的方法是必须使用ng-template。您可以根据后端发送的不同响应切换模板,也可以创建更好的不同组件

<ng-template [ngIf]="hero">
  <div class="name">{{hero.name}}</div>
</ng-template>

答案 1 :(得分:0)

经过几天的挖掘,我终于找到了一个可行的解决方案。

基本上,我是通过http.get加载模板,将远程Head添加到我的头部,然后在运行时与主体生成一个新的动态组件。

现在它可以工作了,我将继续创建一个服务,该服务将从数据库中获取url并返回模板字符串给我,因此我只需要执行1个请求即可将其移至服务。

有一个小问题,远程头所附带的样式和脚本在添加到主头后需要花费一些时间来加载,因此我不得不展示微调器以避免不必要的元素。

export class AppComponent {

    @ViewChild('container', {read: ViewContainerRef, static: false})
        container: ViewContainerRef;
        private componentRef: ComponentRef<{}>;

        constructor(private httpStatus: HTTPStatus,
                          private spinner: NgxSpinnerService,
                          private http: HttpClient,
                          private injectorService: InjectorService) {

        spinner.show();

        http.get('https://somedomain.com/header.php', {responseType: 'text'}).subscribe((header: string) => {
               this.injectorService.injectHeader(header);
        }, error => {
                console.log('error loading header');
        }, () =>  {
                http.get('https://somedomain.com/body.html', {responseType: 'text'}).subscribe((body: string) => {
                    this.injectorService.compileTemplate(this.componentRef, this.container, body);
                });
            });
        }
    }

app.component.html

 <div #container></div>

injector.service.ts

    @Injectable()
    export class InjectorService {


    constructor(private componentFactoryResolver: ComponentFactoryResolver,
                private compiler: Compiler) {}

    public injectHeader(includes: string): void {
        let head = document.head.innerHTML;
        head = head.concat(includes);
        document.head.innerHTML = head;
    }

    public compileTemplate(componentRef: ComponentRef<{}>, container: ViewContainerRef, html: string) {
        const metadata = {
            selector: 'runtime-sample',
            template: html
        };

        const factory = this.createComponentFactorySync(this.compiler, metadata, DynamicComponent);

        if (componentRef) {
            componentRef.destroy();
            componentRef = null;
        }

        componentRef = container.createComponent(factory);

    }

    private createComponentFactorySync(compiler: Compiler, metadata: Component, componentClass: any): ComponentFactory<any> {
        const cmpClass = componentClass || DynamicComponent;
        const decoratedCmp = Component(metadata)(cmpClass);
        @NgModule({ imports: [CommonModule, FormsModule], declarations: [ContentComponent, FilterPipe, decoratedCmp] })
        class RuntimeComponentModule { }

        const module: ModuleWithComponentFactories<any> = compiler.compileModuleAndAllComponentsSync(RuntimeComponentModule);
        return module.componentFactories.find(f => f.componentType === decoratedCmp);
    }
}

由于我加载的身体包含一个

<div id="content">

我可以在ContentComponent中使用

selector: '[id=content]'

要将我的Angular应用加载到远程主体中