【決定版】Angular 2 でイベント駆動型アーキテクチャを構築:子コンポーネントと親コンポーネントの通信をマスターする
Angular 2 で子コンポーネントが親コンポーネントのイベントをリッスンする方法
この機能を実現するには、主に以下の2つの方法があります。
@Output と EventEmitter を使用する
この方法は、子コンポーネントから親コンポーネントへのイベント発行によく使用されます。
手順
子コンポーネントでイベントを定義する
@Output
デコレータを使用してイベントプロパティを宣言します。- イベントプロパティの型は
EventEmitter
にする必要があります。
@Output() someEvent = new EventEmitter<any>();
イベントを発行する
EventEmitter
インスタンスのemit()
メソッドを使用してイベントを発行します。- イベントペイロードを渡すこともできます。
this.someEvent.emit('some data');
@Input
デコレータを使用して子コンポーネントのイベントプロパティをバインドします。- イベントハンドラ関数を定義します。
<child-component (someEvent)="onSomeEvent($event)"></child-component> onSomeEvent(data: any) { // 親コンポーネントでイベントデータを処理する console.log(data); }
例
この例では、子コンポーネント (child-component.ts
) が "someEvent" というイベントを発行し、親コンポーネント (app-component.ts
) がそれをリッスンします。
child-component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component',
template: `
<button (click)="onClick()">ボタンをクリック</button>
`
})
export class ChildComponent {
@Output() someEvent = new EventEmitter<any>();
onClick() {
this.someEvent.emit('ボタンがクリックされました');
}
}
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<child-component (someEvent)="onSomeEvent($event)"></child-component>
`
})
export class AppComponent {
onSomeEvent(data: string) {
console.log('親コンポーネントでイベントを受信しました:', data);
}
}
@ViewChild とイベントリスナーを使用する
この方法は、より直接的な方法で子コンポーネントのイベントをリッスンする場合に使用されます。
親コンポーネントで子コンポーネントインスタンスを取得する
@ViewChild
デコレータを使用して子コンポーネントの参照を取得します。
@ViewChild(ChildComponent) childComponent: ChildComponent;
イベントリスナーを登録する
- 子コンポーネントインスタンスのイベントプロパティにイベントリスナー関数を登録します。
ngOnInit() { this.childComponent.someEvent.subscribe((data) => { this.onSomeEvent(data); }); }
この例は、@ViewChild
とイベントリスナーを使用して "someEvent" イベントをリッスンする親コンポーネントを示しています。
import { Component, ViewChild } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<child-component #child></child-component>
`
})
export class AppComponent {
@ViewChild('child') childComponent: ChildComponent;
ngOnInit() {
this.childComponent.someEvent.subscribe((data) => {
this.onSomeEvent(data);
});
}
onSomeEvent(data: string) {
console.log('親コンポーネントでイベントを受信しました:', data);
}
}
- 上記は基本的な例であり、状況に応じて
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="onClick()">ボタンをクリック</button>
`
})
export class ChildComponent {
@Output() someEvent = new EventEmitter<string>();
onClick() {
this.someEvent.emit('ボタンがクリックされました');
}
}
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<app-child (someEvent)="onSomeEvent($event)"></app-child>
`
})
export class AppComponent {
onSomeEvent(data: string) {
console.log('親コンポーネントでイベントを受信しました:', data);
}
}
このコードの説明
emit()
メソッドに "ボタンがクリックされました" というメッセージを渡します。onClick()
メソッドは、ボタンがクリックされたときにsomeEvent
イベントを発行します。EventEmitter<string>
は、イベントペイロードの型がstring
であることを示します。@Output
デコレータを使ってsomeEvent
という名前のイベントプロパティを宣言します。
onSomeEvent()
メソッドは、イベントデータ (data
) を受け取り、コンソールにログ出力します。(someEvent)="onSomeEvent($event)"
バインディングを使って、someEvent
イベントをonSomeEvent()
メソッドにバインドします。<app-child>
タグを使用して子コンポーネントを挿入します。
実行
このコードを実行すると、ブラウザに以下の画面が表示されます。
<app-child>
<button>ボタンをクリック</button>
</app-child>
ボタンをクリックすると、コンソールに以下のメッセージが表示されます。
親コンポーネントでイベントを受信しました: ボタンがクリックされました
この方法は、子コンポーネントから親コンポーネントへのシンプルなデータ共有に使用できますが、イベントリスニングにはあまり適していません。
- イベントプロパティの型は、イベントデータの型に一致する必要があります。
@Input() someEvent: any;
- 親コンポーネントからバインドされた
someEvent
プロパティを呼び出します。
this.someEvent('ボタンがクリックされました');
- 親コンポーネントからバインドされた
この例では、親コンポーネント (app-component.ts
) は someEvent
というプロパティを子コンポーネント (child-component.ts
) にバインドし、子コンポーネントはボタンクリック時にそのプロパティを呼び出してイベントをトリガーします。
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<child-component [someEvent]="onClick()"></child-component>
`
})
export class AppComponent {
onClick() {
return 'ボタンがクリックされました';
}
}
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="onClick()">ボタンをクリック</button>
`
})
export class ChildComponent {
@Input() someEvent: any;
onClick() {
this.someEvent(); // 親コンポーネントからバインドされたイベントプロパティを呼び出す
}
}
Renderer2 と listen() を使用する
この方法は、より高度なイベントリスニングシナリオに使用できますが、やや複雑で、めったに使用されません。
コンポーネントで Renderer2 を注入する
- コンポーネントのコンストラクタで
Renderer2
を注入します。
constructor(private renderer: Renderer2) { }
- コンポーネントのコンストラクタで
renderer.listen()
メソッドを使用して、イベントリスナーをネイティブ DOM 要素に登録します。
this.renderer.listen(this.buttonElement.nativeElement, 'click', (event) => { // イベント処理 });
この例では、Renderer2
と listen()
を使用してボタンクリックイベントをリッスンする子コンポーネントを示しています。
import { Component, ViewChild, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button #button>ボタンをクリック</button>
`
})
export class ChildComponent {
@ViewChild('button') buttonElement: ElementRef;
constructor(private renderer: Renderer2) { }
ngOnInit() {
this.renderer.listen(this.buttonElement.nativeElement, 'click', (event) => {
console.log('ボタンがクリックされました');
});
}
}
注意事項
- 一般的なイベントリスニングには、
@Output
とEventEmitter
を使用することをお勧めします。 Renderer2
を使用するには、@angular/core
パッケージからインポートする必要があります。
Angular 2 で子コンポーネントが親コンポーネントのイベントをリッスンするには、主に以下の 3 つの方法があります。
@Output
とEventEmitter
を使用する (最も一般的)@Component Inputs
を使用する (シンプルなデータ共有に適している)- **
Renderer2
と
javascript typescript angular