Динамически загружать HTML-шаблон в angular2

Я создал проект, используя 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 иногда возвращает <h1>Good Morning, {{title}}</h1> и иногда <h1>Good Afternoon, {{title}}</h1> в зависимости от текущего времени сервера.

Как добиться этой функциональности?

Я понимаю, что мне нужно определить какую-нибудь функцию загрузчика, которая говорит: loadDynamicTemplate(template_url)

и нужно использовать эту загрузочную функцию в свойстве шаблона Component decorator. В этом случае, когда генерируется main.bundle.JS, он также будет использовать эту функцию. Так что во время выполнения angular вызовет эту функцию и загрузит HTML с помощью ajax и будет использовать его.

Обновление 1

Здесь я обнаружил некоторую разницу между SystemJS и Webpack . Я также обнаружил, что мы можем загружать файлы HTML во время выполнения, если мы можем использовать SystemJS. Поэтому я считаю, что эту проблему можно решить с помощью конфигурации SystemJS. Но для этого в игру вступает другая проблема, хотя я считаю, что это может быть отдельным вопросом. Поэтому я разместил новый вопрос, чтобы разобраться здесь.

Вероятно, если этот вопрос будет решен, я попробую с SystemJS, а затем опубликую решение здесь, если это поможет.

5 ответов

Вы можете использовать [innerHtml] в my-template компонент с чем-то вроде этого (я не тестировал):

@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}}, вы можете использовать компонент ng-dynamic в Suguru Inatomi.

Сначала вы должны установить его:

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. Я добавил пользовательскую кнопку "my-button" с успехом, как в примере с документацией здесь: https://github.com/laco0416/ng-dynamic

Работал с угловой 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);
  }
}

Похоже, что способ сделать это сейчас - установить responseType, когда вы делаете свой запрос. HttpClient-запрос данных не в формате JSON

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

`

Почему бы не иметь все шаблоны в одном файле и отображать их в соответствии с условием.. Как ваш./app.component.html будет выглядеть так:

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

Любая идея о его влиянии на время сборки / размер?

Другие вопросы по тегам