Dynamically add Component in angular 2/4

前端 未结 3 2014
日久生厌
日久生厌 2021-01-07 03:29

How can I add component dynamically?

toolbar.component.ts:

@Component({
  selector: \'app-toolbar\',
  template: \'
相关标签:
3条回答
  • 2021-01-07 04:22

    I have another way of doing it, please check for you case

    html
    <ng-container *ngComponentOutlet="COMPONENT"></ng-container>
    
    .ts
    import { COMPONENT } from './..dir../component'
    

    OR

    html
    <ng-container *ngComponentOutlet="option.component"></ng-container>
    
    .ts
    import { COMPONENT } from './..dir../component'    
    option = {
      component: COMPONENT
    }
    

    OR if it is Dynamic, add the component to entryComponent

    app.module.ts
    import { COMPONENT } from './..dir../component'
    @NgModule({
       declarations: [COMPONENT],
       /.
       ..
       ..
      ./
      entryComponents: [COMPONENT]
    });    
    
    html
    <ng-container *ngComponentOutlet="option.component"></ng-container>
    
    .ts
    /** The COMPONENT is not imported since it is added to entrycomponent**/
    @Input() option;
    
    0 讨论(0)
  • 2021-01-07 04:24

    Expose viewContainerRef on section.component.ts:

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

    Add an output to toolbar.component.ts:

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

    In view.component.ts create a ComponentFactory for TextComponents to add them dynamically to active 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);
        });
       }
    }
    

    StackBlitz example

    0 讨论(0)
  • 2021-01-07 04:27

    I would do it using ngFor view.component.ts:

    @Component({
       selector: 'app-view',
       template: `
         <div class="container">
           <app-toolbar (addEvent)="addEvent($event)"></app-toolbar>
           <div app-type="section" id="SECTION1" class="active">
              <app-text *ngFor="let appText in textArray"></app-text>
           </div>
           <div app-type="section" id="SECTION2"></div>
         </div>
       `
    })
    export class SectionComponent {
       public textArray: string[] = [];
       public addEvent(event: string) : void {
          textArray.push(event);
       }
       ....
    }
    

    toolbar.component.ts:

    import { Component, EventEmitter, Output } from '@angular/core';
    @Component({
      selector: 'app-toolbar',
      template: '<button (click)="addNewText()">Add Text component</button>'
    })
    export class ToolbarComponent {
       @Output addEvent: EventEmitter<string> = new EventEmitter();
       constructor() { }
       addNewText(): void {
          this.addEvent.emit("");
       }
       ....
    }  
    
    0 讨论(0)
提交回复
热议问题