数据绑定ng2组件's模板只设置OnInit

Data-binding ng2 component's template only set OnInit

本文关键字:设置 OnInit ng2 组件 数据绑定      更新时间:2023-09-26

我有一个angular 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 Methods

方法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中的数据绑定将无法工作。

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

有一个详细的答案与例子这里由Radim Kö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 { }

我还没有测试过。试着告诉我进展如何

import {Component, Output, Input,AfterViewInit} from '@angular/core';
 export class codeStepComponent implements AfterViewInit {
     ngAfterViewInit() {
       this.content.innerHTML.replace('{{chapterURL}}', this.chapterURL);
    }
  } 

假设你的页面上有一个{{ChapterUrl}}的实例,这个占位符将在视图初始化后被替换。