Load existing components dynamically Angular 2 Final Release
Update
NgComponentOutlet was introduced in 4.0.0-beta.3 https://github.com/angular/angular/commit/8578682
Coming soon NgComponentOutlet
I see two options to do that:
1) Using ComponentFactoryResolver.
It uses the already generated factory and the code looks something like this:
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;
}
In this case we have to define dynamic component in declarations
and entryComponents
properties within decorator of module
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, DynamicComponent ],
entryComponents: [DynamicComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
- Dynamically Creating Components With Angular 2.0
- Plunker Example
2) Using Compiler
In this case we can only run module compilation by using compiler.compileModuleAndAllComponentsAsync
and then find component from componentFactories array. Your directive might look like this:
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
is a global service that will load and store component factories.
@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 compilation 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);
});
});
}
}
Plunker Example
Hope it helps you!