내용으로 건너뛰기
Angular에서 구성 요소를 동적으로 생성하는 방법

Angular에서 구성 요소를 동적으로 생성하는 방법

이 기사에서는 구성 요소를 동적으로 만드는 방법을 배웁니다. 팝업 모달을 표시하려는 것과 같은 다양한 시나리오에서 구성 요소를 동적으로 로드해야 할 수도 있습니다.

4min read

동적으로 로드할 아래 나열된 구성 요소가 있다고 가정해 보겠습니다.

import { Component, Input } from '@angular/core';
 
@Component({
    selector: 'app-message',
    template: `<h2>{{message}}</h2>
`
})
export class MessageComponent {
    @Input() message: string;
}

MessageComponent를 동적으로 로드하려면 컨테이너가 필요합니다. AppComponent 내부에 MessageComponent를 로드하고 싶다고 가정해 보겠습니다. AppComponent에 컨테이너 요소가 필요합니다.

Template of AppComponent is as below:

<div style="text-align:center">
     <h1>
         Welcome to {{ title }}!
     </h1>
     <template #messagecontainer>
     </template>
 </div>

보시다시피 MessageComponent를 동적으로 로드할 진입점 템플릿 또는 컨테이너 템플릿이 있습니다.

AppComponent에서 다음을 가져와야 합니다.

  1. ViewChild, ViewContainerRef 및 ComponentFactoryResolver @angular/core
  2. @angular/core의 ComponentRef 및 ComponentFactory
  3. message.component의 MessageComponent

필요한 항목을 가져온 후 AppComponnet은 다음 목록과 같습니다.

import {
    Component,
    ViewChild,
    ViewContainerRef,
    ComponentFactoryResolver,
    ComponentRef,
    ComponentFactory
} from '@angular/core';
import { MessageComponent } from './message.component';
 
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})
export class AppComponent {
    title = 'app';
}

Component 클래스 내에서 ViewChild로 템플릿에 액세스할 수 있습니다. 템플릿은 구성 요소를 동적으로 로드하려는 컨테이너입니다. 따라서 ViewConatinerRef로 사원에 액세스해야 합니다.

ViewContainerRef는 하나 이상의 뷰를 연결할 수 있는 컨테이너를 나타냅니다. 여기에는 두 가지 유형의 보기가 포함될 수 있습니다.

  1. Host Views
  2. Embedded Views

호스트 뷰는 createComponent를 사용하여 구성 요소를 인스턴스화하여 생성되고 임베디드 뷰는 createEmbeddedView를 사용하여 임베디드 템플릿을 인스턴스화하여 생성됩니다. 호스트 뷰를 사용하여 MessageComponent를 동적으로 로드합니다.

템플릿 요소를 참조할 entry라는 변수를 만들어 보겠습니다. 또한 구성 요소를 동적으로 로드하는 데 필요한 구성 요소 클래스에 ComponentFactoryResolver 서비스를 삽입했습니다.

export class AppComponent {
    title = 'app';
    @ViewChild('messagecontainer', { read: ViewContainerRef }) entry: ViewContainerRef;
    constructor(private resolver: ComponentFactoryResolver) { }
}

템플릿 요소의 참조인 항목 변수에는 구성 요소를 생성하고 구성 요소를 파괴하는 등의 API가 있습니다.

이제 구성 요소를 생성하려면 함수를 생성해 보겠습니다. 함수 내에서 다음 작업을 수행해야 합니다.

  • 컨테이너 지우기
  • MessageComponent에 대한 팩터리 만들기
  • 팩토리를 사용하여 구성 요소 만들기
  • 구성 요소 참조 인스턴스 메서드를 사용하여 @Input 속성에 대한 값 전달

모든 것을 합치면 createComponent 함수는 아래 목록과 같습니다.

createComponent(message) {
    this.entry.clear();
    const factory = this.resolver.resolveComponentFactory(MessageComponent);
    const componentRef = this.entry.createComponent(factory);
    componentRef.instance.message = message;
}

버튼의 클릭 이벤트에서 createComponent 함수를 호출할 수 있습니다. 템플릿에 두 개의 버튼을 넣고 버튼을 클릭할 때 createComponent 함수를 호출해 보겠습니다.

<div style="text-align:center">
    <h1>
        Welcome to {{ title }}!
    </h1>
    <button (click)="createComponent('Welcome Foo ! ')">Welcome</button>
    <button (click)="createComponent('Foo Again ?')">Not Welcome</button>
    <br />
    <template #messagecontainer>
    </template>
</div>

출력에서 버튼을 클릭할 때 구성 요소가 동적으로 로드되는 것을 볼 수 있습니다.

 welcome app

버튼을 클릭하면 구성 요소가 다른 메시지와 함께 다시 로드됩니다.  componentRef에서 destroy 메서드를 사용하여 구성 요소를 삭제할 수 있습니다.

destroyComponent() {
    this.componentRef.destroy();
}

함수를 수동으로 호출하여 동적으로로드된 구성 요소를 파괴하거나 구성 요소의 ngOnDestroy() 수명 주기 후크 안에 넣어 호스트 구성 요소가 자동으로 파괴될 때 동적으로로드된 구성 요소도 파괴되도록 할 수 있습니다.

모든 것을 종합하면 AppComponent는 아래 목록과 같습니다.

import {
    Component,
    ViewChild,
    ViewContainerRef,
    ComponentFactoryResolver,
    ComponentRef,
    ComponentFactory
} from '@angular/core';
import { MessageComponent } from './message.component';
 
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})
export class AppComponent {
    title = 'app';
    componentRef: any;
 
    @ViewChild('messagecontainer', { read: ViewContainerRef }) entry: ViewContainerRef;
    constructor(private resolver: ComponentFactoryResolver) { }
 
    createComponent(message) {
        this.entry.clear();
        const factory = this.resolver.resolveComponentFactory(MessageComponent);
        this.componentRef = this.entry.createComponent(factory);
        this.componentRef.instance.message = message;
    }
    destroyComponent() {
        this.componentRef.destroy();
    }
}

이 시점에서 응용 프로그램을 실행할 때 AppModule에서 entryComponents를 설정하지 않았기 때문에 오류가 발생합니다. 아래 목록과 같이 설정할 수 있습니다.

import { AppComponent } from './app.component';
import { MessageComponent } from './message.component';
 
@NgModule({
    declarations: [
        AppComponent, MessageComponent
    ],
    imports: [
        BrowserModule
    ],
    providers: [],
    bootstrap: [AppComponent],
    entryComponents: [MessageComponent]
})
export class AppModule { }

Angular에서 구성 요소를 동적으로 로드하기 위해 수행해야 하는 모든 작업입니다.

이 게시물이 마음에 드시나요?

그리고 거기에 있습니다! 이 게시물이 마음에 드시면 좋아요를 누르고 공유해 주세요. 또한 아직 체크아웃하지 않은 분은꼭 체크 Infragistics Ignite UI for Angular! 50+ 빠른 웹 앱을 더 빠르게 코딩하는 데 도움이 되는 재료 기반 Angular 구성 요소가 있습니다.

데모 요청