在Angular 1.x中,我们可以使用HTML标记ng-bind-html
并结合JavaScript调用$sce.trustAsHTML()
实时插入HTML。这使我们有80%的时间,但在使用Angular标签时不会起作用,例如插入使用ng-repeat
或自定义指令的HTML。
为了实现这一点,我们可以使用custom directive that called $compile。
Angular 2中所有这些的等价物是什么?我们可以使用[inner-html]
绑定,但这仅适用于非常简单的HTML标记,例如<b>
。它不会将自定义角度2指令转换为正常运行的HTML元素。 (很像没有$compile
步的Angular 1.x。)Angular 2的$compile
相当于什么?
答案 0 :(得分:11)
In Angular2 you should use DynamicComponentLoader to insert some "compiled content" on the page. So for example if you want to compile next html:
<div>
<p>Common HTML tag</p>
<angular2-component>Some angular2 component</angular2-component>
</div>
then you need to create component with this html as a template (let's call it CompiledComponent
) and use DynamicComponentLoader
to insert this component on the page.
@Component({
selector: 'compiled-component'
})
@View({
directives: [Angular2Component],
template: `
<div>
<p>Common HTML tag</p>
<angular2-component>Angular 2 component</angular2-component>
</div>
`
})
class CompiledComponent {
}
@Component({
selector: 'app'
})
@View({
template: `
<h2>Before container</h2>
<div #container></div>
<h2>After conainer</h2>
`
})
class App {
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
loader.loadIntoLocation(CompiledComponent, elementRef, 'container');
}
}
Check out this plunker
UPD You can create component dynamically right before the loader.loadIntoLocation()
call:
// ... annotations
class App {
constructor(loader: DynamicComponentLoader, elementRef: ElementRef) {
// template generation
const generatedTemplate = `<b>${Math.random()}</b>`;
@Component({ selector: 'compiled-component' })
@View({ template: generatedTemplate })
class CompiledComponent {};
loader.loadIntoLocation(CompiledComponent, elementRef, 'container');
}
}
I personally don't like it, it's look like a dirty hack to me. But here is the plunker
PS Beware that at this moment angular2 is under active development. So situation can be changed at any time.
答案 1 :(得分:5)
不推荐使用DynamicComponentLoader,您可以使用ComponentResolver
如果需要额外的数据操作,可以使用此指令添加管道。它也允许延迟加载,你不需要它,但值得一提。
指令(我发现了这些代码并进行了一些更改,您也可以这样做以使其符合您的口味或按原样使用):
import { Component, Directive, ComponentFactory, ComponentMetadata, ComponentResolver, Input, ReflectiveInjector, ViewContainerRef } from '@angular/core';
declare var $:any;
export function createComponentFactory(resolver: ComponentResolver, metadata: ComponentMetadata): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {};
const decoratedCmp = Component(metadata)(cmpClass);
return resolver.resolveComponent(decoratedCmp);
}
@Directive({
selector: 'dynamic-html-outlet',
})
export class DynamicHTMLOutlet {
@Input() htmlPath: string;
@Input() cssPath: string;
constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) {
}
ngOnChanges() {
if (!this.htmlPath) return;
$('dynamic-html') && $('dynamic-html').remove();
const metadata = new ComponentMetadata({
selector: 'dynamic-html',
templateUrl: this.htmlPath +'.html',
styleUrls: [this.cssPath]
});
createComponentFactory(this.resolver, metadata)
.then(factory => {
const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
this.vcRef.createComponent(factory, 0, injector, []);
});
}
}
如何使用它的示例:
import { Component, OnInit } from '@angular/core';
import { DynamicHTMLOutlet } from './../../directives/dynamic-html-outlet/dynamicHtmlOutlet.directive';
@Component({
selector: 'lib-home',
templateUrl: './app/content/home/home.component.html',
directives: [DynamicHTMLOutlet]
})
export class HomeComponent implements OnInit{
html: string;
css: string;
constructor() {}
ngOnInit(){
this.html = './app/content/home/home.someTemplate.html';
this.css = './app/content/home/home.component.css';
}
}
home.component.html:
<dynamic-html-outlet [htmlPath]="html" [cssPath]="css"></dynamic-html-outlet>
答案 2 :(得分:3)
在阅读了很多内容并接近开启一个新主题后,我决定回答这里只是为了试图帮助其他人。我已经看到Angular 2的最新版本有几处变化。(目前是Beta9)
我会尝试分享我的代码,以避免同样的挫折......
首先,在我们的index.html中
像往常一样,我们应该有这样的事情:
<html>
****
<body>
<my-app>Loading...</my-app>
</body>
</html>
AppComponent(使用innerHTML)
使用此属性,您将能够呈现基本HTML,但您无法通过范围执行类似于Angular 1.x和$ compile的操作:
import {Component} from 'angular2/core';
@Component({
selector: 'my-app',
template: `
<h1>Hello my Interpolated: {{title}}!</h1>
<h1 [textContent]="'Hello my Property bound: '+title+'!'"></h1>
<div [innerHTML]="htmlExample"></div>
`,
})
export class AppComponent {
public title = 'Angular 2 app';
public htmlExample = ' <div>' +
'<span [textContent]="\'Hello my Property bound: \'+title"></span>' +
'<span>Hello my Interpolated: {{title}}</span>' +
'</div>'
}
这将呈现以下内容:
Hello in Interpolated:Angular 2 app!
Hello my Property bound:Angular 2 app!
您好我的插值:{{title}}
AppComponent使用DynamicComponentLoader
here中记录了文档的一个小错误。因此,如果我们记住这一点,我的代码现在看起来应该是这样的:
import {DynamicComponentLoader, Injector, Component, ElementRef, OnInit} from "angular2/core";
@Component({
selector: 'child-component',
template: `
<div>
<h2 [textContent]="'Hello my Property bound: '+title"></h2>
<h2>Hello my Interpolated: {{title}}</h2>
</div>
`
})
class ChildComponent {
title = 'ChildComponent title';
}
@Component({
selector: 'my-app',
template: `
<h1>Hello my Interpolated: {{title}}!</h1>
<h1 [textContent]="'Hello my Property bound: '+title+'!'"></h1>
<div #child></div>
<h1>End of parent: {{endTitle}}</h1>
`,
})
export class AppComponent implements OnInit{
public title = 'Angular 2 app';
public endTitle= 'Bye bye!';
constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {
// dynamicComponentLoader.loadIntoLocation(ChildComponent, elementRef, 'child');
}
ngOnInit():any {
this.dynamicComponentLoader.loadIntoLocation(ChildComponent, this.elementRef, 'child');
}
}
这将呈现以下内容:
Hello in Interpolated:Angular 2 app!
Hello my Property bound:Angular 2 app!
Hello我的属性绑定:ChildComponent标题
您好我的Interpolated:ChildComponent标题
父母结束:再见!
答案 3 :(得分:2)
我认为您所要做的就是使用[innerHTML] =“yourcomponentscopevar”设置要编译html的元素
答案 4 :(得分:0)
Angular提供DynamicComponentLoader
类动态加载html。 DynamicComponentLoader
具有插入组件的方法。 loadIntoLocation
是插入组件的其中之一。
<强> paper.component.ts 强>
import {Component,DynamicComponentLoader,ElementRef,Inject,OnInit} from 'angular2/core';
import { BulletinComponent } from './bulletin.component';
@Component({
selector: 'paper',
templateUrl: 'app/views/paper.html'
}
})
export class PaperComponent {
constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {
}
ngOnInit(){
this.dynamicComponentLoader.loadIntoLocation(BulletinComponent, this.elementRef,'child');
}
}
<强> bulletin.component.ts 强>
import {Component} from 'angular2/core';
@Component({
selector: 'bulletin',
templateUrl: 'app/views/bulletin.html'
}
})
export class BulletinComponent {}
<强> paper.html 强>
<div>
<div #child></div>
</div>
您需要处理的事情很少:
loadIntoLocation
。调用组件构造函数时,尚未创建组件视图。你会收到错误 - AppComponent实例化期间出错!没有组件 元素[object Object]
的指令
无法找到变量子
答案 5 :(得分:0)
看一下这个模块https://www.npmjs.com/package/ngx-dynamic-template
经过长时间的研究,只有这件事帮助了我。其余的解决方案似乎已经过时了。