page change angular typescript angular2-compiler version-compatibility

change - router events angular 6



Equivalente de $ compilar en Angular 2 (7)

Angular TypeScript / ES6 (Angular 2+)

Funciona con AOT + JIT a la vez juntos.

Creé cómo usarlo aquí: https://github.com/patrikx3/angular-compile

npm install p3x-angular-compile

Componente: debe tener un contexto y algunos datos html ...

HTML:

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

Quiero compilar manualmente algunas directivas que contienen HTML. ¿Cuál es el equivalente de $compile en Angular 2?

Por ejemplo, en Angular 1, podría compilar dinámicamente un fragmento de HTML y agregarlo al DOM:

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


Angular 2.3.0 (2016-12-07)

Para obtener todos los detalles, consulte:

  • ¿Cómo puedo usar / crear plantillas dinámicas para compilar componentes dinámicos con Angular 2.0?

Para ver eso en acción:

Los principales:

1) Crear plantilla
2) Crear componente
3) Crear módulo
4) Módulo de compilación
5) Crear (y caché) ComponentFactory
6) usa Target para crear una Instancia del mismo

Una descripción rápida de cómo crear un 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; }

Una forma de inyectar componentes en 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; }

Un fragmento de código sobre cómo crear un ComponentFactory (y almacenarlo en caché)

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

Un fragmento de código sobre cómo usar el resultado anterior

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

La descripción completa con todos los detalles leídos aquí , u observe el ejemplo de trabajo

.

.

OBSOLETO - Angular 2.0 RC5 relacionado (solo RC5)

para ver soluciones anteriores para versiones anteriores de RC, busque en el historial de esta publicación


Para crear dinámicamente una instancia de un componente y adjuntarlo a su DOM, puede usar el siguiente script y debería funcionar en Angular RC :

plantilla html:

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

Componente del cargador

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


Si desea inyectar código html, use la directiva

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

Si desea cargar el componente completo en algún lugar, use DynamicComponentLoader:

DynamicComoponentLoader


Versión angular que he usado - Angular 4.2.0

A Angular 4 se le ocurrió ComponentFactoryResolver para cargar componentes en tiempo de ejecución. Este es un tipo de implementación de $ compile en Angular 1.0 que satisface sus necesidades

En el siguiente ejemplo, estoy cargando el componente ImageWidget dinámicamente en un DashboardTileComponent

Para cargar un componente, necesita una directiva que pueda aplicar a ng-template que le ayudará a colocar el componente dinámico

WidgetHostDirective

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

Esta directiva inyecta ViewContainerRef para obtener acceso al contenedor de vista del elemento que alojará el componente agregado dinámicamente.

DashboardTileComponent (Coloque el componente de soporte para representar el componente dinámico)

Este componente acepta una entrada que proviene de componentes principales o puede cargar desde su servicio en función de su implementación. Este componente cumple la función principal de resolver los componentes en tiempo de ejecución. En este método también puede ver un método llamado renderComponent () que finalmente carga el nombre del componente de un servicio y lo resuelve con ComponentFactoryResolver y finalmente establece los datos en el componente dinámico.

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

Esta es una fábrica de servicios para registrar todos los componentes que desea resolver dinámicamente.

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 cargando en tiempo de ejecución)

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

Agregar Finalmente, agregue este ImageTextWidgetComponent a su módulo de aplicación 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; }

Referencia original de mi blog

Documentación oficial

Descargar código fuente de muestra


este paquete npm me lo hizo más fácil: https://www.npmjs.com/package/ngx-dynamic-template

uso:

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


Nota: Como @BennyBottema menciona en un comentario, DynamicComponentLoader ahora está en desuso, por lo tanto, esta respuesta también.

Angular2 no tiene ningún equivalente de $compile . Puede usar DynamicComoponentLoader y piratear con clases ES6 para compilar su código dinámicamente (consulte 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: ''<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'' ); } }

Pero solo funcionará hasta que el analizador html esté dentro del núcleo angular2.