web-dev-qa-db-fra.com

Charger dynamiquement le template HTML dans angular2

J'ai créé un projet en utilisant angular-cli qui contient AppComponent comme suit:

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

Et app.component.html en tant que

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

Donc, quand je le construit avec ng build, il génère des fichiers comme celui-ci ./ dist/main.bundle.js qui contient du code comme suit -

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

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

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

Cela signifie qu’au moment de la compilation, le compilateur/assembleur lit le fichier HTML et le concatène dans le fichier js généré.

Mais dans mon cas, le code HTML est également dynamique et géré par le contenu du côté serveur. Disons qu'au lieu de html, mon fichier de modèle est app.component.jsp et réside sur un serveur ou un dossier différent.

De plus, ce fichier JSP renvoie parfois <h1>Good Morning, {{title}}</h1> et parfois <h1>Good Afternoon, {{title}}</h1> en fonction de l'heure actuelle du serveur.

Comment réaliser cette fonctionnalité?

Ce que je comprends, c’est que j’ai besoin de définir une sorte de fonction de chargeur, par exemple: loadDynamicTemplate(template_url)

et devez utiliser cette fonction de chargement sur la propriété de modèle de décorateur de composants. Dans ce cas, lorsque main.bundle.JS est généré, il utilisera également cette fonction. Ainsi, à l'exécution, angular appellera cette fonction, chargera le code HTML par ajax et l'utilisera.

Mise à jour 1

Ici J'ai trouvé une différence entre SystemJS et Webpack. J'ai également constaté que nous pouvons charger les fichiers HTML au moment de l'exécution si nous pouvons utiliser SystemJS. Je pense donc que ce problème peut être résolu avec la configuration de SystemJS. Mais pour cela, un autre problème entre en jeu, bien que je pense que cela pourrait être une question distincte. J'ai donc posté une nouvelle question pour résoudre le problème ici .

Probablement si cette question est résolue, je vais essayer avec SystemJS, puis poster la solution ici si cela peut aider.

44

Vous pouvez utiliser [innerHtml] dans un composant my-template avec quelque chose comme ceci (je n'ai pas testé):

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

Pour interpoler un modèle avec certains Good Morning, {{title}}, vous pouvez utiliser le composant "ng-dynamic" de Suguru Inatomi.

Vous devez d'abord l'installer:

npm install --save ng-dynamic

Puis importez dans votre NgModule:

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

Enfin, utilisez-le comme ceci:

@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...
  }
}

Vous pouvez utiliser des composants dans votre modèle en définissant un SharedModule. J'ai ajouté un "my-button" personnalisé avec succès, comme dans l'exemple de documentation ici: https://github.com/laco0416/ng-dynamic

18
Karbos 538

Il semble que la manière de procéder consiste maintenant à définir le responseType lorsque vous faites votre demande. Données HttpClient-Demandant non 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;
        }
      );
  }
}

`

2
nbppp2

travaillé avec angular 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);
  }
}
0
nznoor

Pourquoi ne pas avoir tous les modèles dans un seul fichier et les afficher en fonction de la condition .. Comme votre ./app.component.html ressemblera à ceci:

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

Une idée sur son effet sur le temps de construction/la taille?

0
Kiran