Динамически загружать 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>
Любая идея о его влиянии на время сборки / размер?