Cargue los componentes existentes de forma dinámica Angular 2 Versión final

Intento cargar dinámicamente un componente en la versión final 2.0.0.

Usando RC5 estaba cargando usando el siguiente código:

Crea una directiva para cargar los controles:

import { CheckboxComponent, CheckboxListComponent,DatePickerComponent } from '../components/'; @Directive({ selector: '[ctrl-factory]' }) export class ControlFactoryDirective implements OnChanges { @Input() model: any; constructor(private vcRef: ViewContainerRef, private resolver: ComponentResolver) { } create(cp) { this.resolver.resolveComponent(cp) .then(factory => { const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); this.vcRef.createComponent(factory, 0, injector, []); let ch = this.vcRef.createComponent(factory, 0, injector, []).instance; ch.model = this.model; }); } ngOnChanges() { if (!this.model) return; switch (this.model.type) { case 'checkbox': this.create(CheckboxComponent); break; case 'checkboxlist': this.create(CheckboxListComponent); break; case 'datepicker': this.create(DatePickerComponent); break; default: break; } } } 

Luego cargué esa directiva en mi página así:

 <div ctrl-factory *ngFor="let child of page.childrens" [model]="child"></div> 

Pero después de actualizar desde la versión final rc5 a la 2.0.0, la resolución ya no existe y fue reemplazada por el comstackdor.

Encontré montones de lugares que muestran cómo cargarlo usando diferentes códigos, pero todos son demasiado complejos y no pude hacerlo funcionar.

Tome esto, por ejemplo: ¿Cómo puedo usar / crear una plantilla dinámica para comstackr Componente dynamic con Angular 2.0?

Se ve más específico para ese escenario, el mío, solo necesito cargar el componente y establecer un model llamado @Input.

Una cosa, cuando estaba intentándolo, tuve que crear dinámicamente un module para cada componente y luego agregarle el componente. Pero luego tuve problemas al decir que el componente se estaba configurando en más de un Módulo, intenté eliminarlo en algún lugar y no funcionó.

La mayor parte del código que se muestra, me sale de este enlace: http://blog.laqueueco.net/post/dynamic-component-creation-in-angular-2-rc-5/

E hizo un par de cambios.

Actualizar

Me las arreglo para que funcione, utilizando el siguiente enfoque:

El método de creación ha sido cambiado a

 private create(cp) { @NgModule({ imports: [BrowserModule, ControlsModule], declarations: [] }) class DynamicModule {} this.compiler.compileModuleAndAllComponentsAsync(DynamicModule) .then(({componentFactories}) => { const compFactory = componentFactories.find(x => x.componentType === cp); const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector); const cmpRef = this.vcRef.createComponent(compFactory, 0, injector, []); cmpRef.instance.model = this.model; }); } 

En la mayoría de los lugares que he encontrado, establezca el Componente y configúrelo en el Módulo Dinámico, el problema es que cuando ya está declarando ese mismo componente en un module diferente, angular se va a quejar. La solución en mi caso fue importar el my ControlsModule que tiene todos mis controles exportados.

Actualizar

NgComponentOutlet se introdujo en 4.0.0-beta.3 https://github.com/angular/angular/commit/8578682

Próximamente NgComponentOutlet

Veo dos opciones para hacer eso:

1) Usando ComponentFactoryResolver .

Utiliza la fábrica ya generada y el código se ve así:

 constructor(private vcRef: ViewContainerRef, private resolver: ComponentFactoryResolver) { } create(comp) { const factory = this.resolver.resolveComponentFactory(comp); const compRef = this.vcRef.createComponent(factory); (<any>compRef).instance.model = this.model; } 

En este caso, tenemos que definir el componente dynamic en las declarations y entryComponents properties entryComponents dentro del decorador del module

 @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent, DynamicComponent ], entryComponents: [DynamicComponent], bootstrap: [ AppComponent ] }) export class AppModule { } 
  • Creación dinámica de componentes con Angular 2.0
  • Ejemplo de Plunker

2) Usando el comstackdor

En este caso, solo podemos ejecutar la compilation del module utilizando compiler.compileModuleAndAllComponentsAsync y luego encontrar el componente de la matriz componentFactories. Su directiva puede verse así:

 constructor(private vcRef: ViewContainerRef, private loader: DynamicLoaderService) { } create(comp) { this.loader.createComponentFactory(comp).then(factory => { const compRef = this.vcRef.createComponent(factory); (<any>compRef).instance.model = this.model; }) } 

DynamicLoaderService es un service global que cargará y almacenará fábricas de componentes.

 @Injectable() export class DynamicLoaderService { constructor(protected compiler: Compiler) {} private resolveCompHelper$ = new Subject<any>(); private cache = new Map<string, ComponentFactory<any> | number>(); public createComponentFactory(type: string) : Promise<ComponentFactory<any>> { let factory = this.cache.get(type); // if factory has been already loading if(factory === 1) { return new Promise((resolve) => { // waiting comstacktion of factory const subscriber = this.resolveCompHelper$.subscribe((data) => { if(type !== data.type) return; subscriber.unsubscribe(); resolve(data.factory); }); }); } // factory exists in cache if (factory) { return new Promise((resolve) => resolve(factory)); } const comp = typeMap[type]; // factory startes loading this.cache.set(type, 1); return new Promise((resolve) => { this.compiler.compileModuleAndAllComponentsAsync(createComponentModule(comp)) .then((moduleWithFactories: ModuleWithComponentFactories<any>) => { factory = moduleWithFactories.componentFactories .find(x => x.componentType === comp); this.cache.set(type, factory); this.resolveCompHelper$.next({ type, factory}); resolve(factory); }); }); } } 

Ejemplo de Plunker

Espero que te ayude!

Para mí fue útil ver esta opción basada en una directiva, pero encontré la que se ajusta a mis necesidades en function de los componentes: https://www.ag-grid.com/ag-grid-angular-aot-dynamic-components /

Feliz encoding!