简体   繁体   中英

Angular 4 Update observable via http.get

I'm trying to update an observable which is returned in html from an API call.

I'm wondering if anyone can help me with this.

The html (on another component)

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

and the component is:

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;
            }, () => {
        });
    }
}

so instead of doing a "replace" the observable should just update automatically.

I've tried to use a subscribe and I also tried a promise, however I don't seem to be able to get the syntax to behave.

Can anyone help?

Thanks in advance

1) What you want to achieve is not clear. What I can make out is on success you want to update the dom. 2) Dont use inner html for that and use interpolation or ngModel for the same with a sanitizer. 3) Another approach would be to create a custom reusable directive for the same.

An approach could be:

1) Make a pipe for sanitization:

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) Use it like :

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

where scenarioStepDataDesc is your HTML content.

3) Use a shared module for pipes and other reusable components/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 :)

I suggest you update your <string> f['_body']; change to <string>f.text() , and also innerHTML = "{{innerHtml}}" to [innerHTML]="view" anyway check the below plnkr link as it's doing exactly what you are trying to perform

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

the template is like this

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

the external.html is simple as below

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

here is the running Plnkr

But for String interpolation processing as if the content was in the same template as the parent loading it and bind this to the template scope, which is similar to angular 1 ng-include check this answer as it helps in solving that (instead of re doing it), and note this is for angular 4 and above

using Angular 4.0.0-beta.6's ngComponentOutlet .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM