我有一个角度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
,没有别的...
答案 0 :(得分:4)
2种方法
如果在初始化期间只需要更新一次数据,这很简单。
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);
}
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}}上有一个实例,并且在初始化视图后,将以旧方式替换此占位符。