George Edwards George Edwards - 1 year ago 130
HTTP Question

Data-binding ng2 component's template only set OnInit

I have an angular 2 (RC5) component which makes an HTTP call and sets the result as the template of the component. I want to inject a value into the HTML that is returned by the HTTP call. so for example, one of the lines in the returned HTML is:

<a class="d2h-file-name" href="{{chapterURL}}">app/views/login/login.xml</a>

However, that is rendered exactly as is, without having the chapterURL injected. Presumably, this is because the template isn't set during the initialization process? If so, How should I inject these dynamic values into the templates?

Here's the component.

selector: 'codestep',
template: `<div class="codestep" [innerHTML]="content"></div>`
export class codeStepComponent {
@Input() step: string;
private content: string = '';
private chapterURL;

constructor(private route: ActivatedRoute, private http: Http) { }

ngOnInit() {
this.chapterURL = './diff/' + this.step + '.html';
chapterContent => this.content = chapterContent,
error => this.errorMessage = <any>error);

getChapter(): Observable<any> {
return this.http.get(this.chapterURL)
private extractData(res: Res) {
let body = res._body;
return body;
//Error handling function here...


I have changed the source html file which is returned by the http call, to:

<a class="d2h-file-name" href={{chapterURL}}>app/views/login/login.xml</a>

and then changed the component's template to:

template: `<div class="codestep" [innerHTML]="content|rawHtml"></div>`

is a pipe that sanitises the content with the
function on the
however, I still get the same result, the rendered result is:

<a class="d2h-file-name" href="gitURL">app/views/login/login.xml</a>

if I do
with the component selected in the browser, then the returned resultant object has properties, but the only property listed is
, nothing else...

Answer Source

2 Methods

Method 1 - search and replace

This is simple and easy, if the data only need to be updated once during initialization.

ngOnInit() {
    this.chapterURL = './diff/' + this.step + '.html';
        chapterContent:string => {

            // Pre-process the content
            processedContent = chapterContent.replace('{{chapterURL}}',this.chapterURL);

            this.content = processedContent;
        error => this.errorMessage = <any>error);

Method 2 - dynamic component

Angular 2 does not support component template run time update.

innerHTML will not meet your requirement as Angular2 will not parse the content of it. So data binding within innerHTML will not work.

To archive run time template update, or more precisely, run time template generation is using dynamic component.

There is a detail answer with example here by Radim Köhler:

Following is a very minimalistic example I put together:

import { Component, ComponentRef, ViewChild, ViewContainerRef } from '@angular/core';

import { RuntimeCompiler } from '@angular/compiler';

import { CfModule } from './cf.module';

    selector: 'cf-com',
    template: `
        <button (click)="template1()">Template 1</button>
        <button (click)="template2()">Template 2</button>
        <button (click)="moreChild()">More Child</button>
        <template [ngIf]="childRef" #child></template>`
export class CfCom {
    title = 'Component Factory Test';

    // reference for html element with #child tag
    @ViewChild('child', { read: ViewContainerRef }) protected childComTarget: ViewContainerRef;
    // Child component reference
    protected childRef: ComponentRef<any>;

    constructor(private compiler: RuntimeCompiler) { }

    // Child Input. Use object, not basic type
    childInput = { counter: 0 };

    // Click to get more children
    moreChild() {

    // Click to use template 1
    template1() {
        let t = 'Child:{{j.counter}}';

    // Click to use template 1
    template2() {
        let t = 'Children:{{j.counter}}';

    createChild(t: string) {
        // Destroy child if exist
        if (this.childRef) {
            this.childRef = null;

        // cf-child class
            selector: 'cf-child',
            template: t // template from parameter t
        class CfChildCom {
            j; // will be bind with parent childInput, see below

        this.compiler.compileComponentAsync<any>(CfChildCom, CfModule)
            .then(factory => {
                this.childRef = this.childComTarget.createComponent(factory, 0);

                // This is how parent variable bind with child variable
                this.childRef.instance.j = this.childInput;


import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { COMPILER_PROVIDERS } from '@angular/compiler';

import { CfCom } from './';

    imports: [BrowserModule],
    exports: [CfCom],
    providers: [COMPILER_PROVIDERS],
    declarations: [CfCom]
export class CfModule { }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download