数据绑定ng2组件的模板仅设置OnInit

时间:2016-08-14 22:28:05

标签: javascript http angular typescript

我有一个角度2(RC5)组件,它进行HTTP调用并将结果设置为组件的模板。我想在HTTP调用返回的HTML中注入一个值。例如,返回的HTML中的一行是:

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

然而,在没有注入chapterURL的情况下,完全按原样呈现。据推测,这是因为模板在初始化过程中没有设置?如果是这样,我应该如何将这些动态值注入模板?

这是组件。

@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';
        this.getChapter()
            .subscribe(
            chapterContent => this.content = chapterContent,
            error => this.errorMessage = <any>error);
    }

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

编辑:

我已将http调用返回的源html文件更改为:

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

然后将组件模板更改为:

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

其中rawHtml是使用bypassSecurityTrustHtml()上的DomSanitizationService函数清理内容的管道但是,我仍然得到相同的结果,渲染结果为:

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

如果我使用浏览器中选择的组件ng.probe($0),则返回的结果对象具有属性,但列出的唯一属性是innerHTML,没有别的...

2 个答案:

答案 0 :(得分:4)

2种方法

方法1 - 搜索和替换

如果在初始化期间只需要更新一次数据,这很简单。

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

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

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

方法2 - 动态组件

Angular 2不支持组件模板运行时更新。

innerHTML无法满足您的要求,因为Angular2不会解析其内容。因此,innerHTML中的数据绑定将不起作用。

要归档运行时模板更新,或者更确切地说,运行时模板生成使用动态组件。

RadimKöhler在这里有一个详细的答案示例:     https://stackoverflow.com/a/38888009/1810391

http://plnkr.co/edit/iXckLz?p=preview

以下是我放在一起的非常简约的例子:

<强> cf.com.ts

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

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

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

@Component({
    selector: 'cf-com',
    template: `
        <h1>{{title}}</h1>
        <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() {
        this.childInput.counter++;
    }

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

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

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

        // cf-child class
        @Component({
            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;
            });
    }
}

<强> cf.module.ts

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

import { CfCom } from './cf.com';

@NgModule({
    imports: [BrowserModule],
    exports: [CfCom],
    providers: [COMPILER_PROVIDERS],
    declarations: [CfCom]
})
export class CfModule { }

答案 1 :(得分:1)

我没有测试过这个。试着让我知道它是怎么回事

import {Component, Output, Input,AfterViewInit} from '@angular/core';

 export class codeStepComponent implements AfterViewInit {
     ngAfterViewInit() {
       this.content.innerHTML.replace('{{chapterURL}}', this.chapterURL);
    }
  } 

这假设您在页面上的{{ChapterUrl}}上有一个实例,并且在初始化视图后,将以旧方式替换此占位符。