How can I use/create dynamic template to compile dynamic Component with Angular 2.0?

后端 未结 15 1872
忘掉有多难
忘掉有多难 2020-11-21 05:14

I want to dynamically create a template. This should be used to build a ComponentType at runtime and place (even replace) it somewhere inside of the ho

15条回答
  •  被撕碎了的回忆
    2020-11-21 06:04

    2019 June answer

    Great news! It seems that the @angular/cdk package now has first-class support for portals!

    As of the time of writing, I didn't find the above official docs particularly helpful (particularly with regard to sending data into and receiving events from the dynamic components). In summary, you will need to:

    Step 1) Update your AppModule

    Import PortalModule from the @angular/cdk/portal package and register your dynamic component(s) inside entryComponents

    @NgModule({
      declarations: [ ..., AppComponent, MyDynamicComponent, ... ]
      imports:      [ ..., PortalModule, ... ],
      entryComponents: [ ..., MyDynamicComponent, ... ]
    })
    export class AppModule { }
    

    Step 2. Option A: If you do NOT need to pass data into and receive events from your dynamic components:

    @Component({
      selector: 'my-app',
      template: `
        
        
      `
    })
    export class AppComponent  {
      myPortal: ComponentPortal;
      onClickAddChild() {
        this.myPortal = new ComponentPortal(MyDynamicComponent);
      }
    }
    
    @Component({
      selector: 'app-child',
      template: `

    I am a child.

    ` }) export class MyDynamicComponent{ }

    See it in action

    Step 2. Option B: If you DO need to pass data into and receive events from your dynamic components:

    // A bit of boilerplate here. Recommend putting this function in a utils 
    // file in order to keep your component code a little cleaner.
    function createDomPortalHost(elRef: ElementRef, injector: Injector) {
      return new DomPortalHost(
        elRef.nativeElement,
        injector.get(ComponentFactoryResolver),
        injector.get(ApplicationRef),
        injector
      );
    }
    
    @Component({
      selector: 'my-app',
      template: `
        
        
    ` }) export class AppComponent { portalHost: DomPortalHost; @ViewChild('portalHost') elRef: ElementRef; constructor(readonly injector: Injector) { } ngOnInit() { this.portalHost = createDomPortalHost(this.elRef, this.injector); } onClickAddChild() { const myPortal = new ComponentPortal(MyDynamicComponent); const componentRef = this.portalHost.attach(myPortal); setTimeout(() => componentRef.instance.myInput = '> This is data passed from AppComponent <', 1000); // ... if we had an output called 'myOutput' in a child component, // this is how we would receive events... // this.componentRef.instance.myOutput.subscribe(() => ...); } } @Component({ selector: 'app-child', template: `

    I am a child. {{myInput}}

    ` }) export class MyDynamicComponent { @Input() myInput = ''; }

    See it in action

提交回复
热议问题