Subjectやngrx/storeを使って親コンポーネントから子コンポーネントへイベントを発行する方法
Angularで親コンポーネントから子コンポーネントへイベントを発行する方法
EventEmitterは、コンポーネント間でイベントを発行・受信するための便利な機能です。以下の手順で実装できます。
子コンポーネントでイベントを定義
import { EventEmitter, Output } from '@angular/core';
export class ChildComponent {
@Output() public eventEmitter = new EventEmitter<string>();
public emitEvent() {
this.eventEmitter.emit('イベントが発生しました!');
}
}
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
<child-component (eventEmitter)="onEvent($event)"></child-component>
`
})
export class ParentComponent {
public onEvent(message: string) {
console.log('親コンポーネントでイベントを受け取りました:', message);
}
}
ポイント
@Output
デコレータを使って、子コンポーネントでイベントプロパティを定義します。EventEmitter
型の変数を宣言し、イベント発行時にemit()
メソッドを呼び出します。- 親コンポーネントでは、子コンポーネントのイベントプロパティにバインドし、イベントハンドラ関数を定義します。
- イベントハンドラ関数では、イベント発生時に渡される引数を受け取ることができます。
サービスは、コンポーネント間でデータやロジックを共有するための手段です。以下の手順で実装できます。
サービスを作成
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class EventService {
private eventEmitter = new EventEmitter<string>();
public emitEvent(message: string) {
this.eventEmitter.emit(message);
}
public subscribeToEvent(callback: (message: string) => void) {
return this.eventEmitter.subscribe(callback);
}
}
import { Component, OnInit } from '@angular/core';
import { EventService } from './event.service';
@Component({
selector: 'child-component',
templateUrl: './child.component.html'
})
export class ChildComponent implements OnInit {
constructor(private eventService: EventService) {}
ngOnInit() {
this.eventService.subscribeToEvent((message) => {
console.log('子コンポーネントでイベントを受け取りました:', message);
});
}
public emitEvent() {
this.eventService.emitEvent('イベントが発生しました!');
}
}
import { Component, OnInit } from '@angular/core';
import { EventService } from './event.service';
@Component({
selector: 'parent-component',
templateUrl: './parent.component.html'
})
export class ParentComponent implements OnInit {
constructor(private eventService: EventService) {}
ngOnInit() {
this.eventService.subscribeToEvent((message) => {
console.log('親コンポーネントでイベントを受け取りました:', message);
});
}
}
@Injectable
デコレータを使ってサービスを定義します。subscribe()
メソッドを使ってイベントを受け取り、イベント発生時に渡される引数を受け取ることができます。
- イベント発行が単純な場合や、コンポーネント間の親子関係が明確な場合は、EventEmitterを使うのがおすすめです。
Angularで親コンポーネントから子コンポーネントへイベントを発行するには、EventEmitterとサービスの2つの方法があります。 状況に合わせて適切な方法を選択して、コンポーネント間の通信を実現しましょう。
子コンポーネント (child.component.ts)
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component',
template: `
<button (click)="emitEvent()">イベント発行</button>
`
})
export class ChildComponent {
@Output() public eventEmitter = new EventEmitter<string>();
public emitEvent() {
this.eventEmitter.emit('イベントが発生しました!');
}
}
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
<child-component (eventEmitter)="onEvent($event)"></child-component>
`
})
export class ParentComponent {
public onEvent(message: string) {
console.log('親コンポーネントでイベントを受け取りました:', message);
}
}
サービスを使ったサンプルコード
サービス (event.service.ts)
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class EventService {
private eventEmitter = new EventEmitter<string>();
public emitEvent(message: string) {
this.eventEmitter.emit(message);
}
public subscribeToEvent(callback: (message: string) => void) {
return this.eventEmitter.subscribe(callback);
}
}
import { Component, OnInit } from '@angular/core';
import { EventService } from './event.service';
@Component({
selector: 'child-component',
templateUrl: './child.component.html'
})
export class ChildComponent implements OnInit {
constructor(private eventService: EventService) {}
ngOnInit() {
this.eventService.subscribeToEvent((message) => {
console.log('子コンポーネントでイベントを受け取りました:', message);
});
}
public emitEvent() {
this.eventService.emitEvent('イベントが発生しました!');
}
}
import { Component, OnInit } from '@angular/core';
import { EventService } from './event.service';
@Component({
selector: 'parent-component',
templateUrl: './parent.component.html'
})
export class ParentComponent implements OnInit {
constructor(private eventService: EventService) {}
ngOnInit() {
this.eventService.subscribeToEvent((message) => {
console.log('親コンポーネントでイベントを受け取りました:', message);
});
}
}
実行方法
- 上記のコードを
app.component.ts
とapp.component.html
などのファイルに保存します。 - Angular CLI を使ってプロジェクトをビルドして実行します。
ng serve
補足
- 上記のサンプルコードは、基本的な例です。実際のユースケースに合わせて、コードを修正する必要があります。
感想
Angularで親コンポーネントから子コンポーネントへイベントを発行するその他の方法
Subjectは、イベントとデータの両方を発行・受信できるRxJSのオブジェクトです。以下の手順で実装できます。
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class EventService {
private subject = new Subject<string>();
public emitEvent(message: string) {
this.subject.next(message);
}
public subscribeToEvent(callback: (message: string) => void) {
return this.subject.subscribe(callback);
}
}
import { Component, OnInit } from '@angular/core';
import { EventService } from './event.service';
@Component({
selector: 'child-component',
templateUrl: './child.component.html'
})
export class ChildComponent implements OnInit {
constructor(private eventService: EventService) {}
ngOnInit() {
this.eventService.subscribeToEvent((message) => {
console.log('子コンポーネントでイベントを受け取りました:', message);
});
}
}
import { Component, OnInit } from '@angular/core';
import { EventService } from './event.service';
@Component({
selector: 'parent-component',
templateUrl: './parent.component.html'
})
export class ParentComponent implements OnInit {
constructor(private eventService: EventService) {}
ngOnInit() {
// イベント発行
this.eventService.emitEvent('イベントが発生しました!');
}
}
- Subjectは、イベントとデータの両方を発行・受信できます。
- RxJSの知識が必要になります。
ngrx/storeは、状態管理のためのライブラリです。以下の手順で実装できます。
ストアモジュールをインストール
npm install @ngrx/store @ngrx/effects
import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
@NgModule({
imports: [
StoreModule.forRoot({
// reducers
})
]
})
export class AppModule {}
アクションを作成
export const INCREMENT = 'INCREMENT';
export class IncrementAction {
readonly type = INCREMENT;
constructor(public readonly payload: number) {}
}
リデューサーを作成
export function counterReducer(state = 0, action: IncrementAction) {
switch (action.type) {
case INCREMENT:
return state + action.payload;
default:
return state;
}
}
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
@Injectable({
providedIn: 'root'
})
export class EventService
angular typescript