0

J'essaie de mettre à jour une observable qui est retournée en html à partir d'un appel API. Je me demande si quelqu'un peut m'aider avec ça.Angular 4 Mise à jour observable via http.get

Le html (sur un autre composant)

<common-content [theme]="theme" ></common-content> 

et le composant est:

import { Component, OnInit, Input } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 
import { ThemeModel } from '../../models'; 
import 'rxjs/add/operator/toPromise'; 

@Component({ 
    selector: 'common-content', 
    template: `<div innerHTML = "{{innerHtml}}"></div>` 
}) 

export class CommonContentComponent implements OnInit { 
    @Input() page: string; 
    @Input() theme: ThemeModel; 
    innerHtml: string; 

    constructor(private http: Http) { 
    } 

    ngOnInit() { 
     this.populatePage(); 
    } 

    populatePage(){ 
     let thisUrl = 'myPage.html'; 
     this.http.get(thisUrl).subscribe(f => { 
      var content = <string>f['_body']; 
      this.innerHtml = content.replace("{{theme.Name}}", this.theme.name); 
      }, (error) => { 
       let e = error; 
      },() => { 
     }); 
    } 
} 

donc au lieu de faire un "remplacer" l'observable devrait simplement mettre à jour automatiquement.

J'ai essayé d'utiliser un abonnement et j'ai aussi essayé une promesse, mais je ne semble pas pouvoir obtenir la syntaxe pour se comporter.

Quelqu'un peut-il aider?

Merci à l'avance

+0

Pourriez-vous montrer le contenu de f – Carsten

+0

juste une puce, au lieu de ' f [ '_body']; 'changer pour' f.text() 'plus sûr –

+2

Je ne comprends pas ce que vous demandez. Qu'essayez-vous d'accomplir? Votre code envoie une requête HTTP, et lorsque la réponse revient, initialise le champ innerHtml de votre composant avec le corps de la réponse (après un remplacement). Quoi d'autre aimeriez-vous réaliser? –

Répondre

0

je vous suggère de mettre à jour votre <string> f['_body']; changement <string>f.text(), et aussi innerHTML = "{{innerHtml}}"-[innerHTML]="view" vérifier de toute façon le lien ci-dessous de plnkr comme il est fait exactement ce que vous essayez d'effectuer

this._http.get(link).subscribe(f => { 
    this.loading = false; 
      var content = <string>f.text(); 
      this.view = content.replace("{{theme.Name}}", this.theme.name); 
      }, (error) => { 
       this.loading = false; 
       console.error(error); 
       alert(error); 
      }); 

la modèle est comme ce

content <button (click)="open('external.html')">Open Page</button> 
     <strong *ngIf="loading">LOADING...</strong> 
     <div [innerHTML]="view"></div> 

le external.html est s œuvre comme ci-dessous

me playing around with this theme with name 
<b> 
    {{theme.Name}} 
</b> 

ici est la course Plnkr

Mais pour le traitement d'interpolation chaîne comme si le contenu était dans le même modèle que le chargement parent et se lier this à la portée du modèle, qui est similaire à 1 ng angulaire - inclure cette vérification answer car elle contribue à résoudre que (au lieu de le faire re), et est à noter que ce angulaire 4 et au-dessus

en utilisant Angular 4.0.0-beta.6 ngComponentOutlet.

+0

Merci pour les commentaires Theophilus, malheureusement quand j'utilise "[innerHTML] =" view "" comme vous le décrivez ci-dessus, j'obtiens {{theme.Name}} sur la vue au lieu des données, donc je dois encore faire semblant faire l'interpolation en utilisant une commande "replace" alors que je préférerais que l'observable gère le remplacement comme il le fait normalement. Donc, au lieu de voir {{theme.Name}}, je voudrais voir "Yellow Theme" (ou tout ce que j'ai mis dans le fichier de configuration). – Mick

+0

Vérifiez le lien plnkr, il le remplace, ou vous essayez de faire en sorte que angulaire prenne en charge le contenu innerHTML chargé comme le fonctionne 'ng-include'? –

+0

oui. L'idée est que j'ai plusieurs thèmes. J'ai quelques fichiers qui sont communs parmi ces thèmes. Donc, je veux charger dans les composants sans charger un thème commun, parce que je veux utiliser le thème d'origine et ne pas le changer. – Mick

1

1) Ce que vous voulez réaliser n'est pas clair. Ce que je peux faire ressortir c'est que vous voulez mettre à jour le dom. 2) N'utilisez pas html interne pour cela et utilisez l'interpolation ou ngModel pour le même avec un désinfectant. 3) Une autre approche serait de créer une directive réutilisable personnalisée pour le même.

Une approche pourrait être:

1) Faire un tuyau pour aseptisation:

import { Pipe, PipeTransform } from '@angular/core'; 
import { DomSanitizer } from '@angular/platform-browser'; 
/** 
* 
* @export 
* @class SafeHtmlPipe 
* @implements {PipeTransform} 
*/ 
@Pipe({ 
    name: 'safeHtml' 
}) 
export class SafeHtmlPipe implements PipeTransform { 
    /** 
    * 
    * @param {DomSanitizer} sanitizer 
    * @memberof SafeHtmlPipe 
    */ 
    constructor(private sanitizer: DomSanitizer) { } 
    /** 
    * 
    * @param {any} style 
    * @returns 
    * @memberof SafeHtmlPipe 
    */ 
    transform(style) { 
    // return this.sanitizer.bypassSecurityTrustStyle(style); 
    return this.sanitizer.bypassSecurityTrustHtml(style); 
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see docs 
    } 
} 

2) utiliser comme:

<div class="card_description" [innerHTML]="scenarioStepDataDesc | safeHtml"></div> 

où scenarioStepDataDesc est votre contenu HTML.

3) Utilisez un module partagé pour les tuyaux et autres composants réutilisables/directives

import { NgModule } from '@angular/core'; 
import { CommonModule } from '@angular/common'; 
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 
import { MaterialModule } from '../material/material.module'; 
import { BlockUIModule } from 'ng-block-ui'; 
import { AutoCompleteComponent } from './components/autoComplete/autoComplete.component'; 
import { DialogDataComponent } from './components/dialog/dialog.component'; 
import { SafeHtmlPipe } from './pipes/safeHtml.pipe'; 
/** 
* 
* @export 
* @class SharedModule 
*/ 
@NgModule({ 
    imports: [CommonModule, FormsModule, MaterialModule, BlockUIModule, ReactiveFormsModule], 
    exports: [ 
    CommonModule, 
    FormsModule, 
    MaterialModule, 
    BlockUIModule, 
    ReactiveFormsModule, 
    AutoCompleteComponent, 
    DialogDataComponent, 
    SafeHtmlPipe 
    ], 
    declarations: [AutoCompleteComponent, DialogDataComponent, SafeHtmlPipe] 
}) 
export class SharedModule { } 

Enjoy :)

+0

Bonjour Shubhendu, j'ai essayé d'écrire un service, mais je n'arrive pas à le faire fonctionner non plus. – Mick

+0

s'il vous plaît définir à nouveau l'énoncé du problème car il n'est pas clair, alors je vais essayer d'aider. –

+0

Bien sûr, le problème est que je charge du code HTML à partir d'une autre page. Je voudrais que l'interpolation fonctionne sur le html que je viens de charger afin que je puisse voir le résultat interpolé dans la vue plutôt que le texte brut. En d'autres termes, je vois {{theme.name}} dans la vue, mais ce que je veux voir dans la vue, ce sont les données configurées dans le fichier de configuration du thème qui pourrait être "Yellow Theme" à la place. – Mick