以角度2/4动态添加Component

bui*_*huy 1 components angular-services viewchild angular

如何动态添加组件?

toolbar.component.ts:

@Component({
  selector: 'app-toolbar',
  template: '<button>Add Text component</button>'
})
export class ToolbarComponent {
   constructor() { }
}  
Run Code Online (Sandbox Code Playgroud)

section.component.ts:

@Component({
   selector: 'div[app-type=section]',
   template: ''
})
export class SectionComponent {
   constructor() { }
}  
Run Code Online (Sandbox Code Playgroud)

text.component.ts:

@Component({
   selector: 'app-text',
   template: '<p>This is dynamically component</p>'
})
export class TextComponent {
   constructor() { }
}  
Run Code Online (Sandbox Code Playgroud)

view.component.ts:

@Component({
   selector: 'app-view',
   template: `<div class="container">
<app-toolbar></app-toolbar>
<div app-type="section" id="SECTION1" class="active"></div>
<div app-type="section" id="SECTION2"></div>
</div>`
})
export class SectionComponent {}
Run Code Online (Sandbox Code Playgroud)

当我点击ToolBarComponent时,我想将TextComponent添加到具有"active"类的SectionComponent.

jef*_*j13 6

viewContainerRefsection.component.ts上公开:

@Component({
   selector: 'div[app-type=section]',
   template: ''
})
export class SectionComponent {
  @Input() active: boolean;

   constructor(public viewContainerRef: ViewContainerRef) { }
} 
Run Code Online (Sandbox Code Playgroud)

将输出添加到toolbar.component.ts:

@Component({
  selector: 'app-toolbar',
  template: '<button (click)="addComponentClick.emit()">Add Text component</button>'
})
export class ToolbarComponent {
  @Output() addComponentClick = new EventEmitter();
   constructor() { }
} 
Run Code Online (Sandbox Code Playgroud)

view.component.ts中创建一个ComponentFactoryTextComponents,将它们动态添加到活动的 SectionComponents:

import { Component, AfterViewInit, ViewChildren, QueryList, ElementRef, ComponentFactoryResolver, ComponentFactory, OnInit } from '@angular/core';
import { TextComponent } from './text.component';
import { SectionComponent } from './section.component';

@Component({
   selector: 'app-view',
   template: `<div class="container">
<app-toolbar (addComponentClick)="onAddComponentClick()"></app-toolbar>
<div app-type="section" id="SECTION1" [active]="true"></div>
<div app-type="section" id="SECTION2"></div>
</div>`
})
export class ViewComponent implements AfterViewInit, OnInit {
  @ViewChildren(SectionComponent) sections: QueryList<SectionComponent>;
  activeSections: SectionComponent[];
  textComponentFactory: ComponentFactory<TextComponent>;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {  }

  ngOnInit() {
    this.textComponentFactory = this.componentFactoryResolver.resolveComponentFactory(TextComponent);
  }

  ngAfterViewInit() {
    this.activeSections = this.sections.reduce((result, section, index) => {
      if(section.active) {
        result.push(section);
      }
      return result;
    }, []);
  }

   onAddComponentClick() {
    this.activeSections.forEach((section) => {
      section.viewContainerRef.createComponent(this.textComponentFactory);
    });
   }
}
Run Code Online (Sandbox Code Playgroud)

StackBlitz的例子