相当于Angular 2中的$编译

我想手动编译一些包含HTML的指令。 在Angular 2中, $compile的等价物是多less?

例如,在Angular 1中,我可以dynamic地编译HTML片段并将其附加到DOM:

 var e = angular.element('<div directive></div>'); element.append(e); $compile(e)($scope); 

Angular 2.3.0 (2016-12-07)

要得到所有的细节检查:

  • 我如何使用/创builddynamic模板来编译dynamic组件与Angular 2.0?

在行动中看到:

  • 观察一个工作的重击者 (使用2.3.0+)

校长:

1)创build模板
2)创build组件
3)创build模块
4)编译模块
6)创build(和caching)ComponentFactory 5)使用Target创build一个实例

快速概述如何创build一个组件

 createNewComponent (tmpl:string) { @Component({ selector: 'dynamic-component', template: tmpl, }) class CustomDynamicComponent implements IHaveDynamicData { @Input() public entity: any; }; // a component for this particular template return CustomDynamicComponent; } 

一种如何将组件注入到NgModule的方法

 createComponentModule (componentType: any) { @NgModule({ imports: [ PartsModule, // there are 'text-editor', 'string-editor'... ], declarations: [ componentType ], }) class RuntimeComponentModule { } // a module for just this Type return RuntimeComponentModule; } 

一个代码片段如何创build一个ComponentFactory (并caching它)

 public createComponentFactory(template: string) : Promise<ComponentFactory<IHaveDynamicData>> { let factory = this._cacheOfFactories[template]; if (factory) { console.log("Module and Type are returned from cache") return new Promise((resolve) => { resolve(factory); }); } // unknown template ... let's create a Type for it let type = this.createNewComponent(template); let module = this.createComponentModule(type); return new Promise((resolve) => { this.compiler .compileModuleAndAllComponentsAsync(module) .then((moduleWithFactories) => { factory = _.find(moduleWithFactories.componentFactories , { componentType: type }); this._cacheOfFactories[template] = factory; resolve(factory); }); }); } 

一个代码片段如何使用上面的结果

  // here we get Factory (just compiled or from cache) this.typeBuilder .createComponentFactory(template) .then((factory: ComponentFactory<IHaveDynamicData>) => { // Target will instantiate and inject component (we'll keep reference to it) this.componentRef = this .dynamicComponentTarget .createComponent(factory); // let's inject @Inputs to component instance let component = this.componentRef.instance; component.entity = this.entity; //... }); 

所有细节的完整描述在这里阅读 ,或观察工作示例

OBSOLETE – Angular 2.0 RC5相关(仅RC5)

看到以前的RC版本的解决scheme,请通过这篇文章的历史search

注意:由于@BennyBottema在评论中提到,DynamicComponentLoader现在已被弃用,因此这个答案也是如此。


Angular2没有任何$编译的等价物。 您可以使用DynamicComoponentLoader并使用ES6类来dynamic编译您的代码(请参阅这个plunk ):

 import {Component, DynamicComponentLoader, ElementRef, OnInit} from 'angular2/core' function compileToComponent(template, directives) { @Component({ selector: 'fake', template , directives }) class FakeComponent {}; return FakeComponent; } @Component({ selector: 'hello', template: '<h1>Hello, Angular!</h1>' }) class Hello {} @Component({ selector: 'my-app', template: '<div #container></div>', }) export class App implements OnInit { constructor( private loader: DynamicComponentLoader, private elementRef: ElementRef, ) {} ngOnInit() {} { const someDynamicHtml = `<hello></hello><h2>${Date.now()}</h2>`; this.loader.loadIntoLocation( compileToComponent(someDynamicHtml, [Hello]) this.elementRef, 'container' ); } } 

但是它只会在htmlparsing器在angular2内部之前起作用。

angular度版我已经使用 – angular4.2.0

Angular 4提出了ComponentFactoryResolver来在运行时加载组件。 这是在Angular 1.0中的$ compile的一种实现,它可以满足您的需求

在下面这个例子中,我将ImageWidget组件dynamic加载到DashboardTileComponent中

为了加载一个组件,你需要一个可以应用到ng-template的指令,这将有助于放置dynamic组件

WidgetHostDirective

  import { Directive, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[widget-host]', }) export class DashboardTileWidgetHostDirective { constructor(public viewContainerRef: ViewContainerRef) { } } 

此指令注入ViewContainerRef以访问将承载dynamic添加组件的元素的视图容器。

DashboardTileComponent (占位符组件来呈现dynamic组件)

该组件接受来自父组件的input,或者可以根据您的实现从服务中加载该组件。 此组件在运行时解决组件的主要angular色。 在这个方法中,您还可以看到一个名为renderComponent()的方法,最终从服务中加载组件名称并使用ComponentFactoryResolver进行parsing,最后将数据设置为dynamic组件。

 import { Component, Input, OnInit, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core'; import { DashboardTileWidgetHostDirective } from './DashbardWidgetHost.Directive'; import { TileModel } from './Tile.Model'; import { WidgetComponentService } from "./WidgetComponent.Service"; @Component({ selector: 'dashboard-tile', templateUrl: 'app/tile/DashboardTile.Template.html' }) export class DashboardTileComponent implements OnInit { @Input() tile: any; @ViewChild(DashboardTileWidgetHostDirective) widgetHost: DashboardTileWidgetHostDirective; constructor(private _componentFactoryResolver: ComponentFactoryResolver,private widgetComponentService:WidgetComponentService) { } ngOnInit() { } ngAfterViewInit() { this.renderComponents(); } renderComponents() { let component=this.widgetComponentService.getComponent(this.tile.componentName); let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component); let viewContainerRef = this.widgetHost.viewContainerRef; let componentRef = viewContainerRef.createComponent(componentFactory); (<TileModel>componentRef.instance).data = this.tile; } } 

DashboardTileComponent.html

  <div class="col-md-2 col-lg-2 col-sm-2 col-default-margin col-default"> <ng-template widget-host></ng-template> </div> 

WidgetComponentService

这是一个服务工厂,用于注册要dynamicparsing的所有组件

 import { Injectable } from '@angular/core'; import { ImageTextWidgetComponent } from "../templates/ImageTextWidget.Component"; @Injectable() export class WidgetComponentService { getComponent(componentName:string) { if(componentName==="ImageTextWidgetComponent"){ return ImageTextWidgetComponent } } } 

ImageTextWidgetComponent (我们在运行时加载的组件)

 import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'dashboard-imagetextwidget', templateUrl: 'app/templates/ImageTextWidget.html' }) export class ImageTextWidgetComponent implements OnInit { @Input() data: any; constructor() { } ngOnInit() { } } 

添加最后添加这个ImageTextWidgetComponent到你的应用程序模块作为entryComponent

 @NgModule({ imports: [BrowserModule], providers: [WidgetComponentService], declarations: [ MainApplicationComponent, DashboardHostComponent, DashboardGroupComponent, DashboardTileComponent, DashboardTileWidgetHostDirective, ImageTextWidgetComponent ], exports: [], entryComponents: [ImageTextWidgetComponent], bootstrap: [MainApplicationComponent] }) export class DashboardModule { constructor() { } } 

TileModel

  export interface TileModel { data: any; } 

我的博客的原始参考

正式文件

Angular TypeScript / ES6(Angular 2+)

与AOT + JIT一起工作。

我创build了如何在这里使用它: https : //github.com/patrikx3/angular-compile

 npm install p3x-angular-compile 

组件:应该有一个上下文和一些HTML数据…

HTML:

 <div [p3x-compile]="data" [p3x-compile-context]="ctx">loading ...</div> 

为了创build一个组件的实例并将其附加到您的DOM,您可以使用以下脚本,并应在Angular RC中工作:

html模板:

 <div> <div id="container"></div> <button (click)="viewMeteo()">Meteo</button> <button (click)="viewStats()">Stats</button> </div> 

加载程序组件

 import { Component, DynamicComponentLoader, ElementRef, Injector } from '@angular/core'; import { WidgetMeteoComponent } from './widget-meteo'; import { WidgetStatComponent } from './widget-stat'; @Component({ moduleId: module.id, selector: 'widget-loader', templateUrl: 'widget-loader.html', }) export class WidgetLoaderComponent { constructor( elementRef: ElementRef, public dcl:DynamicComponentLoader, public injector: Injector) { } viewMeteo() { this.dcl.loadAsRoot(WidgetMeteoComponent, '#container', this.injector); } viewStats() { this.dcl.loadAsRoot(WidgetStatComponent, '#container', this.injector); } } 

这个npm包让我更容易: https : //www.npmjs.com/package/ngx-dynamic-template

用法:

 <ng-template dynamic-template [template]="'some value:{{param1}}, and some component <lazy-component></lazy-component>'" [context]="{param1:'value1'}" [extraModules]="[someDynamicModule]"></ng-template> 

如果你想注入html代码使用指令

 <div [innerHtml]="htmlVar"></div> 

如果要在某个地方加载整个组件,请使用DynamicComponentLoader:

https://angular.io/docs/ts/latest/api/core/DynamicComponentLoader-class.html