Angular 動的コンポーネントの作成と活用法
概要
この文章では、Angularフレームワークを使用して動的コンポーネントを作成する方法を詳しく解説します。動的コンポーネントは、アプリケーションの柔軟性と再利用性を高めるための強力な手法です。
Angularで動的にコンポーネントを追加する
ボタンをクリックした時に、Angularコンポーネントを動的に挿入する方法を記載します。
以下の2つに分けて解説しています。
- Angularコンポーネントを動的に挿入(→ まずは場所を考えずに挿入します。)
- 特定の場所に、Angularコンポーネントを動的に挿入
Step1. Angularコンポーネントを動的に挿入
動的に挿入するコンポーネントを作成
ここでは、以下のようなとても簡単なコンポーネントを作成します。
src/app/dynamic/dynamic.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-dynamic',
template: `<p>dynamic works!</p>`
})
export class DynamicComponent {
}
ボタンをhtml上に配置
ボタンをクリックすると、メソッド onButtonClick()
が実行され、Angularコンポーネントを生成できるようにします。
src/app/app.component.html
<div>
<button (click)="onButtonClick()">click!</button>
</div>
動的にAngularコンポーネントを挿入
ComponentFactory
、 viewContainerRef
を利用し、Angularコンポーネントを挿入します。
- 初期処理
ngOnInit()
で、動的にDynamicComponent
をコンパイルできる状態にします。 - クリックされた時に、
viewContainerRef.createComponent
を利用し、コンポーネント生成を実行します。
src/app/app.component.ts
import { Component, ComponentFactory, ComponentFactoryResolver, OnInit, ViewContainerRef } from '@angular/core';
import { DynamicComponent } from './dynamic/dynamic.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
factory: ComponentFactory<DynamicComponent>;
constructor(
public viewContainerRef: ViewContainerRef,
private resolver: ComponentFactoryResolver) { }
ngOnInit() {
this.factory = this.resolver.resolveComponentFactory(DynamicComponent);
}
onButtonClick() {
this.viewContainerRef.createComponent(this.factory);
}
}
@NgModule.entryComponents
に、動的に挿入するコンポーネントを追加
(3)まで実装し、ボタンをクリックすると、ERROR Error: No component factory found for DynamicComponent. Did you add it to @NgModule.entryComponents?
というエラーが表示されます。
指示される通りに entryComponents
を追加すると、ボタンを押すと動的にAngularコンポーネントを表示するところまで完成します。
src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DynamicComponent } from './dynamic/dynamic.component';
@NgModule({
declarations: [
AppComponent,
DynamicComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent],
entryComponents: [DynamicComponent] // Add entryComponents here!
})
export class AppModule { }
Step2. 特定の場所に、Angularコンポーネントを動的に挿入
(Step1 が完了している前提で) @ViewChild
を利用することで、コンポーネントを置く場所を指定することが可能になります。component.ts
とhtml
をそれぞれ編集します。
src/app/app.component.ts
export class AppComponent implements OnInit {
factory: ComponentFactory<DynamicComponent>;
// @ViewChild を追加
@ViewChild('dynamic', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;
// 不要になった ViewContainerRef をコンストラクタから削除
constructor(
private resolver: ComponentFactoryResolver) { }
(以下略)
html
には、コンポーネントを挿入したい箇所に、上記の @ViewChild
定義した #dynamic
タグを追加します。以下では、ボタンの上にコンポーネントが生成されるようにします。
src/app/app.component.html
<div #dynamic></div>
<div>
<button (click)="onButtonClick()">click!</button>
</div>
上記を完了したうえでボタンをクリックすると、ボタンの上に"dynamic works!"と表示されることが確認できます。
補足
今回の実装ではDOM要素を追加しているだけなので、DomSanitizer
を利用して実装することもできます。
コンポーネントを生成するロジックをServiceクラスに置くことで、ほかのコンポーネントから呼び出すことができるようにできます。詳しくは「参考」に載せているページで確認できます。
注意点
動的コンポーネントを使用する際は、ライフサイクルの管理やメモリリークに注意する必要があります。コンポーネントが不用になった際には適切にクリーンアップを行うことが大切です。
参考文献
タイトル | リンク |
---|---|
Angular Documentation | https://angular.io/docs |
Building Dynamic Components in Angular | https://www.example.com |
Q&A
Q1: 動的コンポーネントはどのような場面で使うべきですか?
A1: ユーザーの操作に応じて、画面上にコンポーネントを動的に追加したい場合に特に有効です。
Q2: メモリリークを防ぐためにはどうすれば良いですか?
A2: コンポーネントが不要になった際に、明示的にクリーンアップを行い、リファレンスを解放することが重要です。
Q3: 動的コンポーネントを使用する際のパフォーマンスへの影響はありますか?
A3: 適切に管理されていれば影響は少ないですが、不必要に多くのコンポーネントを生成するとパフォーマンスに影響を及ぼす可能性があります。