【问题标题】:Dynamically load HTML template in angular2在angular2中动态加载HTML模板
【发布时间】:2017-04-08 18:18:27
【问题描述】:

我使用 angular-cli 创建了一个项目,其中包含 AppComponent 如下:

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';
}

app.component.html一样

<h1>
  Good Morning, {{title}}
</h1>

因此,当我使用ng build 构建它时,它会生成一些类似 ./dist/main.bundle.js 的文件,其中包含如下代码-

/* 586 */
/***/ function(module, exports) {

module.exports = "<h1>\n  Good Morning, {{title}}\n</h1>\n"

/***/ },
/* 587 */

这意味着,在构建时,编译器/捆绑器正在读取 html 文件并将它们连接到生成的 js 文件中。

但在我的情况下,html 也是 动态 并且从服务器端驱动内容。可以说,我的模板文件不是 html,而是 app.component.jsp 并且完全驻留在某个不同的服务器或文件夹上。

此外,JSP 文件有时会返回 &lt;h1&gt;Good Morning, {{title}}&lt;/h1&gt; 有时&lt;h1&gt;Good Afternoon, {{title}}&lt;/h1&gt; 取决于当前服务器时间。

如何实现这个功能?

我的理解是,我需要定义某种加载器函数说:loadDynamicTemplate(template_url)

并且需要在组件装饰器模板属性上使用该加载器功能。在这种情况下,当生成 main.bundle.JS 时,它也会使用该函数。所以在运行时 Angular 会调用这个函数并通过 ajax 加载 HTML 并使用它。

更新 1

Here 我发现 SystemJS 和 Webpack 之间有些区别。我还发现如果我们可以使用 SystemJS,我们可以在运行时加载 HTML 文件。所以我相信这个问题可以通过 SystemJS 配置来解决。但是为此,另一个问题开始发挥作用,尽管我相信这可能是一个单独的问题。所以我发布了一个新问题来解决它here

如果这个问题得到解决,我可能会尝试使用 SystemJS,如果有帮助,请在此处发布解决方案。

【问题讨论】:

  • 这在 Angular2 中并不常见。见stackoverflow.com/questions/34784778/…
  • 在我的情况下,我的所有组件都将具有相同的行为。将我的所有组件定义为动态组件确实是有问题的。所以实际上我正在寻找这样的东西。 template: "&lt;my-template url='./app.component.html'&gt;&lt;/my-template&gt;"。这里my-template 可能是一个指令,它将动态加载HTML。此外,它应该保持所有其他功能完好无损。因为它应该与templateUrl: './app.component.html' 一样工作
  • 我知道这不太常见。实际上,我有一个带有 Adob​​e AEM 的服务器端内容管理系统。我想将其用于其出色的创作功能。由于 Angular2 是一个很棒的框架,我相信应该有一些解决方法。 (无需更改这么多代码,我只想通过 AJAX 调用在运行时提供模板)。请帮忙。
  • 您可以在现有组件中加载 HTML,但只能加载纯 HTML。如果你要将它变成 Angular 组件、指令或数据或事件绑定,它必须在已编译组件的模板中。
  • @ParthaSarathiGhosh,您尝试过 ng-dynamic 库吗?我认为它确实可以完成这项工作:github.com/laco0416/ng-dynamic

标签: angular typescript aem angular-cli angular2-compiler


【解决方案1】:

您可以在 my-template 组件中使用类似这样的 [innerHtml](我没有测试):

@Component({
    selector: 'my-template',
    template: `
<div [innerHtml]="myTemplate">
</div>
`})
export public class MyTemplate {
    private myTemplate: any = "";
    @Input() url: string;
    constructor(http: Http) {
        http.get("/path-to-your-jsp").map((html:any) => this.myTemplate = html);
    }
}

【讨论】:

  • Good Morning, {{title}} 之类的东西无法以这种方式解析 {{title}}
  • 好 Plunker 曾经在这里:plnkr.co/edit/uzcYiN 我为@Partha Sarathi Ghosh 发布了一个示例
  • 如何强制默认设置为项目文件夹中的某些 html 模板提供服务?
  • 我不明白。你可以看看 webpack 文档:webpack.github.io/docs
  • Angular 无法解析 [innerHTML] 内部的绑定,因此如果 title 发生更改,它不会正确更新。你可以做的是创建一个GreetingComponent,它从你的服务器接收原始数据并在 Angular 中处理它。
【解决方案2】:

要使用 Good Morning, {{title}} 插入模板,您可以使用 Suguru Inatomi 的“ng-dynamic”组件。

首先你必须安装它:

npm install --save ng-dynamic

然后导入到你的 NgModule 中:

@NgModule({
  imports: [
    ...
    DynamicComponentModule.forRoot({}),
    ...
  ],
  ...
})
export class AppModule {}    

最后像这样使用它:

@Component({
  selector: 'app-root',
  template: '<div *dynamicComponent="template; context: bindings;"></div>'
})
export class AppComponent {
  bindings: any = {title: "Chuck Norris"};
  template: string = `
    <h1>Good Morning, {{title}}</h1>
  `;
  constructor(http: Http) {
    http.get("/path-to-your-jsp").map((html:string) => this.template = html); //<- You may set bindings in request headers...
  }
}

您可以通过定义 SharedModule 在模板中使用组件。我在此处的文档示例中添加了一个自定义“我的按钮”,如:https://github.com/laco0416/ng-dynamic

【讨论】:

  • 如果我有这么多的绑定变量和方法,这里写代码的方式是很复杂的。在这里,我找到了有关 SystemJs 和 Webpack 的更多信息。我用调查结果更新了我的问题。
  • 为什么会报错:不能绑定到 'dynamicComponent',因为它不是 'div' 的已知属性?
  • 也许你错过了明星? *dynamicComponent
  • 生产构建时出现错误“TypeError: Cannot read property 'element' of undefined”
【解决方案3】:

使用角度 6

import { Component, Input } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  template: `
            <div [innerHtml]="myTemplate">
            </div>
          `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private myTemplate: any = '';
  constructor(http: HttpClient) {
    http.get('/service-path', {responseType: 'text'}).subscribe(data => this.myTemplate = data);
  }
}

【讨论】:

    【解决方案4】:

    现在执行此操作的方法似乎是在您提出请求时设置 responseType。 HttpClient-Requesting non-JSON data `

    @Component({
      selector: 'my-template',
      template: '<div [innerHtml]="myTemplate"></div>'
    })
    export public class MyTemplate {
      private myTemplate: any = "";
      @Input() url: string;
      constructor(http: Http) {
        http.get("/path-to-your-jsp", { responseType: 'text' })
          .subscribe(
            (data: string) => {
              this.myTemplate = html;
            }
          );
      }
    }
    

    `

    【讨论】:

      【解决方案5】:

      为什么不将所有模板放在一个文件中并根据条件显示它们.. 就像你的 ./app.component.html 看起来像:

      <div *ngIf="isWorld" >
        <h1>  Hello World </h1>
      </div>
      <div *ngIf="isUniverse" >
        <h1>  Hello Universe </h1>
      </div>
      

      知道它对构建时间/大小的影响吗?

      【讨论】:

        猜你喜欢
        • 2016-03-29
        • 2013-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-29
        • 2017-08-27
        • 2012-10-09
        • 1970-01-01
        相关资源
        最近更新 更多