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
を用い、コンポーネントインスタンスを直接操作する場合にはViewChild
やContentChild
が有効です。
これらを理解・適切に使い分けることで、より柔軟で拡張性の高いUIを実現できます。