동적으로 컴포넌트 불러오기

동적으로 컴포넌트를 불러오는 내용으로서 angular 14 미만 버전에서 사용되는 내용입니다.
angular14 이상에서는 ReflectiveInjector, ComponentFactoryResolver 를 사용할 수 없으므로 다음장에서 다시 다루겠습니다.

import {
  Component,
  NgModule,
  Inject,
  ViewChild,
  ViewContainerRef,
  ReflectiveInjector,
  ComponentFactoryResolver,
  
  AfterViewInit} from '@angular/core';


import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';

import { Component1 } from './component1';
import { Component2 } from './component2';



@Component({
  selector: 'app-modal-dynamic',
  template: `
      <ng-template #container></ng-template>
  `
})

export class DynamicComponent implements AfterViewInit {
  @ViewChild('container', {read: ViewContainerRef, static: true}) private container?: ViewContainerRef;
  private componentData: any;
  constructor(
      private dialogRef: MatDialogRef<FairnessComponent>,
      @Inject(MAT_DIALOG_DATA) public data: { title: string },
      private resolver: ComponentFactoryResolver,
  ) {
  }
  public ngAfterViewInit(): void {
    setTimeout(() => { this.create(); }, 1);
  }

  public create(): void {
    switch (this.data.title) {
      case 'Component1':
        this.componentData = {
          component: Component1,
          inputs: { data: this.data}
        };
        break;
      case 'Component2':
        this.componentData = {
          component: Component2,
          inputs: { data: this.data}
        };
        break;
     
    }

    if (!this.componentData || !this.componentData.component) {
      return;
    }
    // Inputs need to be in the following format to be resolved properly
    const inputProviders = Object.keys(this.componentData.inputs).map((inputName) => {
      return { provide: inputName, useValue: this.componentData.inputs[inputName] };
    });
    
    const resolvedInputs = ReflectiveInjector.resolve(inputProviders);

    // We create an injector out of the data we want to pass down and this components injector
    if (this.container) {
      const injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.container.parentInjector);
      // We create a factory out of the component we want to create
      const factory = this.resolver.resolveComponentFactory(this.componentData.component);

      // We create the component using the factory and the injector
      const component = factory.create(injector) as any; // as any type으로 형을 선언해 주어야 component.instance.popclosed 에서 에러가 발생하지 않음
      this.container.insert(component.hostView, 0);

      // 컴포넌트의 액션을 리스닝 한다.
      component.instance.popclosed.subscribe(() => {
        component.destroy();
        this.dialogRef.close();
      });
    }
  }
}

@NgModule({
  declarations: [
    Component1,
    Component2
  ],
  imports: [
    ..........
  ],
  exports: [
    Component1
  ]
})
export class DynamicComponentModule { }

Table of contents 목차

평점을 남겨주세요
평점 : 2.5
총 투표수 : 1