Solución:
actualizar
Ejemplo de Angular 5 StackBlitz
actualizar
ngComponentOutlet
fue agregado a 4.0.0-beta.3
actualizar
Hay un NgComponentOutlet
trabajo en progreso que hace algo similar https://github.com/angular/angular/pull/11235
RC.7
Plunker ejemplo RC.7
// Helper component to add dynamic components
@Component(
selector: 'dcl-wrapper',
template: ``
)
export class DclWrapper
@ViewChild('target', read: ViewContainerRef) target: ViewContainerRef;
@Input() type: Type;
cmpRef: ComponentRef;
private isViewInitialized:boolean = false;
constructor(private componentFactoryResolver: ComponentFactoryResolver, private compiler: Compiler)
updateComponent()
if(!this.isViewInitialized)
return;
if(this.cmpRef)
// when the `type` input changes we destroy a previously
// created component before creating the new one
this.cmpRef.destroy();
let factory = this.componentFactoryResolver.resolveComponentFactory(this.type);
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
ngOnChanges()
this.updateComponent();
ngAfterViewInit()
this.isViewInitialized = true;
this.updateComponent();
ngOnDestroy()
if(this.cmpRef)
this.cmpRef.destroy();
Ejemplo de uso
// Use dcl-wrapper component
@Component(
selector: 'my-tabs',
template: `
Tabs
`
)
export class Tabs
@Input() tabs;
@Component(
selector: 'my-app',
template: `
Hello name
`
)
export class App
// The list of components to create tabs from
types = [C3, C1, C2, C3, C3, C1, C1];
@NgModule(
imports: [ BrowserModule ],
declarations: [ App, DclWrapper, Tabs, C1, C2, C3],
entryComponents: [C1, C2, C3],
bootstrap: [ App ]
)
export class AppModule
Ver también angular.io CARGADOR DE COMPONENTES DINÁMICOS
versiones mas antiguasxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Esto cambió nuevamente en Angular2 RC.5
Actualizaré el ejemplo a continuación, pero es el último día antes de las vacaciones.
Este ejemplo de Plunker demuestra cómo crear componentes dinámicamente en RC.5
Actualización: use ViewContainerRef.createComponent ()
Porque DynamicComponentLoader
está en desuso, el enfoque debe actualizarse nuevamente.
@Component(
selector: 'dcl-wrapper',
template: ``
)
export class DclWrapper
@ViewChild('target', read: ViewContainerRef) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private resolver: ComponentResolver)
updateComponent()
if(!this.isViewInitialized)
return;
if(this.cmpRef)
this.cmpRef.destroy();
this.resolver.resolveComponent(this.type).then((factory:ComponentFactory) =>
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
);
ngOnChanges()
this.updateComponent();
ngAfterViewInit()
this.isViewInitialized = true;
this.updateComponent();
ngOnDestroy()
if(this.cmpRef)
this.cmpRef.destroy();
Ejemplo de Plunker RC.4
Ejemplo de Plunker beta.17
Actualización: use loadNextToLocation
export class DclWrapper
@ViewChild('target', read: ViewContainerRef) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;
constructor(private dcl:DynamicComponentLoader)
updateComponent()
// should be executed every time `type` changes but not before `ngAfterViewInit()` was called
// to have `target` initialized
if(!this.isViewInitialized)
return;
if(this.cmpRef)
this.cmpRef.destroy();
this.dcl.loadNextToLocation(this.type, this.target).then((cmpRef) =>
this.cmpRef = cmpRef;
);
ngOnChanges()
this.updateComponent();
ngAfterViewInit()
this.isViewInitialized = true;
this.updateComponent();
ngOnDestroy()
if(this.cmpRef)
this.cmpRef.destroy();
Ejemplo de Plunker beta.17
original
No estoy del todo seguro de su pregunta cuáles son sus requisitos, pero creo que esto debería hacer lo que quiere.
los Tabs
el componente obtiene un array de tipos pasados y crea “pestañas” para cada elemento en el array.
@Component(
selector: 'dcl-wrapper',
template: ``
)
export class DclWrapper
constructor(private elRef:ElementRef, private dcl:DynamicComponentLoader)
@Input() type;
ngOnChanges()
if(this.cmpRef)
this.cmpRef.dispose();
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) =>
this.cmpRef = cmpRef;
);
@Component(
selector: 'c1',
template: `c1
`
)
export class C1
@Component(
selector: 'c2',
template: `c2
`
)
export class C2
@Component(
selector: 'c3',
template: `c3
`
)
export class C3
@Component(
selector: 'my-tabs',
directives: [DclWrapper],
template: `
Tabs
`
)
export class Tabs
@Input() tabs;
@Component(
selector: 'my-app',
directives: [Tabs]
template: `
Hello name
`
)
export class App
types = [C3, C1, C2, C3, C3, C1, C1];
Ejemplo de Plunker beta.15 (no basado en su Plunker)
También hay una forma de pasar datos que se pueden pasar al componente creado dinámicamente como (someData
necesitaría ser pasado como type
)
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) =>
cmpRef.instance.someProperty = someData;
this.cmpRef = cmpRef;
);
También hay algo de soporte para usar la inyección de dependencia con servicios compartidos.
Para obtener más detalles, consulte https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html
No soy lo suficientemente bueno para los comentarios. Arreglé el plunker de la respuesta aceptada para que funcione para rc2. Nada especial, los enlaces a la CDN simplemente se rompieron, eso es todo.
'@angular/core':
main: 'bundles/core.umd.js',
defaultExtension: 'js'
,
'@angular/compiler':
main: 'bundles/compiler.umd.js',
defaultExtension: 'js'
,
'@angular/common':
main: 'bundles/common.umd.js',
defaultExtension: 'js'
,
'@angular/platform-browser-dynamic':
main: 'bundles/platform-browser-dynamic.umd.js',
defaultExtension: 'js'
,
'@angular/platform-browser':
main: 'bundles/platform-browser.umd.js',
defaultExtension: 'js'
,
https://plnkr.co/edit/kVJvI1vkzrLZJeRFsZuv?p=preview
hay un componente listo para usar (compatible con rc5) ng2-steps que usa Compiler
para inyectar el componente al contenedor del paso y el servicio para conectar todo (sincronización de datos)
import Directive , Input, OnInit, Compiler , ViewContainerRef from '@angular/core';
import StepsService from './ng2-steps';
@Directive(
selector:'[ng2-step]'
)
export class StepDirective implements OnInit
@Input('content') content:any;
@Input('index') index:string;
public instance;
constructor(
private compiler:Compiler,
private viewContainerRef:ViewContainerRef,
private sds:StepsService
)
ngOnInit()
//Magic!
this.compiler.compileComponentAsync(this.content).then((cmpFactory)=>
const injector = this.viewContainerRef.injector;
this.viewContainerRef.createComponent(cmpFactory, 0, injector);
);
Puedes añadir valor a nuestra información contribuyendo tu experiencia en las crónicas.