Angularにおけるコンポーネント間の連携

Angularでは、アプリケーションを構成する複数のコンポーネント同士がデータやイベントをやり取りすることで、画面の状態を管理します。
本章では、親子間の通信に使われる@Input()@Output()、イベント伝播に用いるEventEmitter、そしてコンポーネントの参照を行うViewChild / ContentChildについて解説します。

1. @Input() / @Output() デコレータによる親子通信

子コンポーネントが親からデータを受け取るには@Input()、親が子からイベントを受け取るには@Output()を使います。これにより、コンポーネントを疎結合に保ちながら双方向のやり取りが可能になります。

■ 親 → 子:@Input()

子コンポーネント(child.component.ts):

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: '<p>メッセージ: {{ message }}</p>'
})
export class ChildComponent {
  @Input() message: string = '';
}

親コンポーネントテンプレート:

<app-child [message]="'こんにちは!'"></app-child>

■ 子 → 親:@Output() と EventEmitter

子コンポーネント(child.component.ts):

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: '<button (click)="notifyParent()">通知</button>'
})
export class ChildComponent {
  @Output() notify = new EventEmitter<string>();

  notifyParent() {
    this.notify.emit('子コンポーネントからの通知');
  }
}

親コンポーネントテンプレート:

<app-child (notify)="onChildNotify($event)"></app-child>
<p>受け取ったメッセージ: {{ childMessage }}</p>

親コンポーネントクラス:

export class ParentComponent {
  childMessage = '';

  onChildNotify(message: string) {
    this.childMessage = message;
  }
}

2. EventEmitterの使い方

EventEmitterは、イベントを発行するための仕組みで、主に@Output()と組み合わせて使います。型指定(ジェネリクス)により、送信するデータの型も明示できます。

例:

@Output() clicked = new EventEmitter<number>();
this.clicked.emit(42);

受信側は$eventを使って値を取得できます。

<app-child (clicked)="handleClick($event)"></app-child>

3. ViewChild / ContentChild の基本

子コンポーネントやテンプレート要素にアクセスする必要がある場合は、@ViewChild()@ContentChild()を使います。これにより、親コンポーネント側から子コンポーネントのプロパティやメソッドを直接操作できます。

■ ViewChild(子コンポーネントを直接参照)

子コンポーネント(child.component.ts):

export class ChildComponent {
  sayHello() {
    console.log('こんにちは!');
  }
}

親コンポーネント(parent.component.ts):

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from './child.component';

@Component({
  selector: 'app-parent',
  template: '<app-child></app-child>'
})
export class ParentComponent implements AfterViewInit {
  @ViewChild(ChildComponent) child!: ChildComponent;

  ngAfterViewInit() {
    this.child.sayHello();
  }
}

■ ContentChild(ng-contentで投げられたコンテンツにアクセス)

主に投げ込みスロットで使われるng-contentの中身を取得したいときに@ContentChild()を使います。

@Component({
  selector: 'app-panel',
  template: '<div class="panel"><ng-content></ng-content></div>'
})
export class PanelComponent implements AfterContentInit {
  @ContentChild('contentRef') contentElement: any;

  ngAfterContentInit() {
    console.log(this.contentElement);
  }
}

親側テンプレート:

<app-panel>
  <div #contentRef>ここが投げ込まれる</div>
</app-panel>

まとめ

Angularのコンポーネント間通信は、@Input()@Output()による親子間の明確なデータフローが基本です。
イベント発火にはEventEmitterを用い、コンポーネントインスタンスを直接操作する場合にはViewChildContentChildが有効です。
これらを理解・適切に使い分けることで、より柔軟で拡張性の高いUIを実現できます。

採用情報 長谷川 横バージョン
SHARE
PHP Code Snippets Powered By : XYZScripts.com