Angularでコンポーネントを動的に作成する方法
この記事では、コンポーネントを動的に作成する方法を学習します。ポップアップモーダルを表示したい場合など、さまざまなシナリオでコンポーネントを動的にロードする必要がある場合があります。
以下にリストされているコンポーネントがあり、動的にロードすると仮定します。
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では、以下をインポートする必要があります。
- ViewChild、ViewContainerRef、および ComponentFactoryResolver を @angular/core から取得
- @angular/core からの ComponentRef と ComponentFactory
- 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 つ以上のビューをアタッチできるコンテナを表します。これには、2 種類のビューを含めることができます。
- Host Views
- 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関数を呼び出すことができます。テンプレートに2つのボタンを配置し、ボタンをクリックすると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>
出力では、ボタンをクリックするとコンポーネントが動的にロードされていることがわかります。

ボタンをクリックすると、コンポーネントが別のメッセージでリロードされます。 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で動的にロードするために必要なのはこれだけです。
この投稿が好きですか?
そして、これで完了です!この投稿が気に入ったら、いいねして共有してください。また、まだチェックしていない方は、インフラジスティックスIgnite UI for Angular、ぜひチェックしてください!50+のマテリアルベースのAngularコンポーネントがあり、高速なWebアプリをより速くコーディングするのに役立ちます。