Equivalente de $ compile em Angular 2

Eu quero compilar manualmente algumas diretivas contendo HTML. Qual é o equivalente de $compile em Angular 2?

Por exemplo, no Angular 1, eu poderia compilar dinamicamente um fragment de HTML e anexá-lo ao DOM:

 var e = angular.element('
'); element.append(e); $compile(e)($scope);

Angular 2.3.0 (2016-12-07)

Para obter todos os detalhes, verifique:

  • Como posso usar / criar modelo dynamic para compilar o componente dynamic com o Angular 2.0?

Para ver isso em ação:

  • observe um plunker de trabalho (trabalhando com 2.3.0+)

Os principais:

1) Criar modelo
2) Criar Componente
3) Criar Módulo
4) Módulo Compile
5) Crie (e armazene em cache) o ComponentFactory
6) use o Target para criar uma instância dele

Uma visão geral rápida de como criar um componente

 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; } 

Uma maneira de injetar componentes no 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; } 

Um trecho de código como criar um ComponentFactory (e armazená-lo em cache)

 public createComponentFactory(template: string) : Promise> { 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); }); }); } 

Um trecho de código como usar o resultado acima

  // here we get Factory (just compiled or from cache) this.typeBuilder .createComponentFactory(template) .then((factory: ComponentFactory) => { // 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; //... }); 

A descrição completa com todos os detalhes lidos aqui , ou observe o exemplo de trabalho

.

.

OBSOLETO – Angular 2.0 RC5 relacionado (apenas RC5)

Para ver as soluções anteriores das versões anteriores do RC, pesquise no histórico deste post

Nota: Como @BennyBottema menciona em um comentário, DynamicComponentLoader agora está obsoleto, portanto, esta é a resposta.


Angular2 não tem nenhum equivalente de $ compile . Você pode usar DynamicComoponentLoader e hackear com classs ES6 para compilar seu código dinamicamente (veja este 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: '

Hello, Angular!

' }) class Hello {} @Component({ selector: 'my-app', template: '
', }) export class App implements OnInit { constructor( private loader: DynamicComponentLoader, private elementRef: ElementRef, ) {} ngOnInit() {} { const someDynamicHtml = `

${Date.now()}

`; this.loader.loadIntoLocation( compileToComponent(someDynamicHtml, [Hello]) this.elementRef, 'container' ); } }

Mas funcionará apenas até que o analisador html esteja dentro do núcleo angular2.

Versão angular eu tenho usado – Angular 4.2.0

O Angular 4 surgiu com o ComponentFactoryResolver para carregar componentes em tempo de execução. Este é um tipo de implementação igual a $ compile no Angular 1.0 que atende a sua necessidade

Neste exemplo abaixo, estou carregando o componente ImageWidget dinamicamente em um DashboardTileComponent

Para carregar um componente, você precisa de uma diretiva que possa ser aplicada ao ng-template, que ajudará a colocar o componente dynamic

WidgetHostDirective

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

Essa diretiva injeta ViewContainerRef para obter access ao contêiner de exibição do elemento que hospedará o componente adicionado dinamicamente.

DashboardTileComponent (componente Placeholder para renderizar o componente dynamic)

Esse componente aceita uma input proveniente de um componente pai ou que você pode carregar de seu serviço com base em sua implementação. Esse componente está desempenhando o papel principal para resolver os componentes no tempo de execução. Nesse método, você também pode ver um método chamado renderComponent () que, por fim, carrega o nome do componente de um serviço e resolve com o ComponentFactoryResolver e, finalmente, define os dados para o componente 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); (componentRef.instance).data = this.tile; } } 

DashboardTileComponent.html

  

WidgetComponentService

Esta é uma fábrica de serviços para registrar todos os componentes que você deseja resolver dinamicamente

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

ImageTextWidgetComponent (componente que estamos carregando em tempo de execução)

 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() { } } 

Adicionar Finalmente, adicione este ImageTextWidgetComponent ao seu módulo de aplicativo como 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; } 

Referência original do meu blog

Documentação Oficial

Download do Código Fonte da Amostra

esse pacote npm facilitou para mim: https://www.npmjs.com/package/ngx-dynamic-template

uso:

  

Para dinamicamente criar uma instância de um componente e anexá-lo ao seu DOM, você pode usar o seguinte script e trabalhar no Angular RC :

template html:

 

Componente Loader

 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); } } 

Angular TypeScript / ES6 (Angular 2+)

Trabalha com AOT + JIT de uma só vez.

Eu criei como usá-lo aqui: https://github.com/patrikx3/angular-compile

 npm install p3x-angular-compile 

Componente: deve ter um contexto e alguns dados html …

Html:

 
loading ...

Se você quiser injetar uma diretiva de uso de código html

 

Se você quiser carregar todo o componente em algum lugar, use DynamicComponentLoader:

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