Skip to content

Instantly share code, notes, and snippets.

@spali
Created December 6, 2016 11:59
Show Gist options
  • Save spali/91ec412d9b321cdd3c9d9da00e2f56ed to your computer and use it in GitHub Desktop.
Save spali/91ec412d9b321cdd3c9d9da00e2f56ed to your computer and use it in GitHub Desktop.
Dynamic Module with dynamic Component in Angular 2
import { Component, OnInit, ViewContainerRef, ComponentRef, Compiler, NgModule, OnDestroy } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'dynamic-container',
templateUrl: 'static.component.html'
})
export class DynamicContainerComponent implements OnInit, OnDestroy {
protected componentRef: ComponentRef<any>;
constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {
}
ngOnInit() {
this.destroy();
var component = this.createDynamicComponent('<h1>dynamic Content</h1>');
var module = this.createDynamicModule(component);
this.compiler.compileModuleAndAllComponentsAsync(module)
.then(moduleWithComponentFactories => {
var componentFactory = moduleWithComponentFactories.componentFactories.find(element => element.componentType === component);
this.componentRef = this.vcRef.createComponent(componentFactory);
});
}
ngOnDestroy() {
this.destroy();
}
private destroy() {
if (this.componentRef) {
this.componentRef.destroy();
}
}
private createDynamicComponent(template: string) {
@Component({
selector: 'dynamic-content',
template: template
})
class DynamicComponent { };
return DynamicComponent;
}
private createDynamicModule(component: any) {
@NgModule({
declarations: [component]
})
class DynamicModule { };
return DynamicModule;
}
}
@spali
Copy link
Author

spali commented Dec 6, 2016

found also a possibility to use TemplateRef's. Combination of the gits with the following code should work.

// Source: https://codegists.com/code/angular-2-dynamically-add-component/
import { Component, Directive, TemplateRef, ViewContainerRef, Injector,
  ComponentFactoryResolver, Renderer } from '@angular/core';
 
@Component({
  selector: 'alert',
  template: `
    <div class="alert alert-success" role="alert">
      <ng-content></ng-content>
    </div>
  `
})
export class AlertComponent {
}
 
@Directive({ selector: 'template[alert]' })
export class AlertDirective {
 
  constructor(
    templateRef: TemplateRef,
    viewContainerRef: ViewContainerRef,
    injector: Injector,
    componentFactoryResolver: ComponentFactoryResolver,
    renderer: Renderer
  ) {
    this.templateRef = templateRef;
    this.viewContainerRef = viewContainerRef;
    this.injector = injector;
    this.componentFactoryResolver = componentFactoryResolver;
    this.renderer = renderer;
  }
 
  ngOnInit() {
    this._windowFactory = this.componentFactoryResolver.resolveComponentFactory(AlertComponent);
    const nodes = this.getContentNodes(this.templateRef);
    this._windowRef = this.viewContainerRef.createComponent(this._windowFactory, 0, this.injector, nodes);
    console.log('This is your AlertComponent instance: ', this._windowRef.instance);
  }
 
  getContentNodes(content) {
    if (content instanceof TemplateRef) {
      return [this.viewContainerRef.createEmbeddedView(content).rootNodes];
    } else {
      return [[this.renderer.createText(null, `${content}`)]];
    }
  }
}

@spali
Copy link
Author

spali commented Dec 7, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment