|||||||||||||||||||||

なんぶ電子

- 更新: 

Angularのコンポーネント間のデータ受け渡し

Angular @Input @Output

以前Angularの公式チュートリアルに沿ってサービスを設定した際にも少し触れましたが、改めてAngularの親コンポーネントと子コンポーネント間のデータの受け渡しについて整理します。

@Input

親から子へデータを渡す際は、子側で@Input()を利用します。

@がついているのでこれはデコレーターです。デコレータとはDI(依存性の注入)用の関数だと考えるとわかりやすいかもしれません。デコレーターを利用することで既存のクラスやプロパティに後から機能を追加することができます。

子コンポーネントで@Inputを定義すると、親コンポーネントからデータを受け取ることができます。

Inputをimportした上で、コンポーネントクラスのプロパティの先頭に@Input()を加えます。

この@Input()は後に書かれているプロパティを、親からデータを受け取れるように初期化してくれます

child.component.ts

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

export class ItemDetailComponent {
  @Input() public userName:string = '';
}

親コンポーネントのhtml(テンプレート)で子コンポーネントのセレクターを記述する際に、属性に@Inputをつけたプロパティ名を、値に渡したい値を設定します。固定値での運用も可能ですが、これをバインドすることで親からデータを動的に渡すことができます。

parent.component.html

...
<app-child [userName]="userNameParent"></app-child>
...

parent.component.ts

...
public userNameParent:string='ユーザー名';
...

@Inputで設定した子コンポーネントのプロパティは子コンポーネント内で変更ができますが、変更は親には伝わりませんし、親から別の値が来るとその値で上書きされますので基本的には子側で値を操作はしません。@Inputに設定したプロパティを子コンポーネントで変更したい場合は、後述する@Outputを使って親にデータの変更を依頼します。

また、親がデータを変更した際のイベントを取得したい場合は、OnChangesライフサイクルフックを使います。

child.component.ts

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
...
ngOnChanges(changes: SimpleChanges) {
  console.log(changes[変数名]['previousValue']+'→'+changes[変数名]['currentValue']);
}
...

@Output

子コンポーネントから親コンポーネントにデータを渡したい場合は@Outputを使います。これも子側に記述しますが、仕組みは@Inputとは若干違い、親にデータを直接渡すのではなく、データを含んだイベントを発生させてそれを親に拾ってもらうイメージになります。

そのため@Outputを設定するプロパティはEventEmitter型でないといけません。EventEmitterはイベントを送出することができるオブジェクトです。

child.component.ts

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

@Output() userNameChagne = new EventEmitter<string>();
...
//HTML内で呼び出す
public changeName(strNewName:string):void {
  userNameChagne.emit(strNewName);
}
...

親のhtml(テンプレート)に子が発生させたイベントを受け取れるようにイベントバインディングの記述をします。

parent.component.html

...
<app-child (userNameChagne)="someMethod($event)"></app-child>
...

EventEmitterとして設定したプロパティ名を()で囲い、実行させたいメソッドを設定します。

$eventには子コンポーネントのEventEmmiterのemmitの引数に渡したオブジェクト(ジェネリクスに設定したオブジェクト、ここではstring)が入ります。

@Outputは、@Inputで子コンポーネントに設定したプロパティを子側から変更したいという時にも利用します。子のイベントを受け取った親は、このプロパティに結びついている親のプロパティを受け取った値に変更します。こうすることで親と子の値の同期が取れます。

次のように@Inputと@Outputの両方を設定すると、双方向のデータ通信が実現可能です。

parent.component.html

...
<app-child [userName]="userNameParent" (nameChagneEvent)="someMethod($event)"></app-child>
...

また、単に親子間で共通の値を保持したいだけなら、[()]を使った双方向データバインディングに書き換えることができます。

ただし、双方向データバインディングにする場合は「property」という@Inputプロパティがあったら、@Outputは「propertyChange」という名前にしなければいけません。

先の例でいうとuserNameという@Inputのプロパティがあるので、@OutputのプロパティはuserNameChangeとすれば[(userName)]="userNameParent"と省略形を利用することができます。

筆者紹介


自分の写真
がーふぁ、とか、ふぃんてっく、とか世の中すっかりハイテクになってしまいました。プログラムのコーディングに触れることもある筆者ですが、自分の作業は硯と筆で文字をかいているみたいな古臭いものだと思っています。 今やこんな風にブログを書くことすらAIにとって代わられそうなほど技術は進んでいます。 生活やビジネスでPCを活用しようとするとき、そんな第一線の技術と比べてしまうとやる気が失せてしまいがちですが、おいしいお惣菜をネットで注文できる時代でも、手作りの味はすたれていません。 提示されたもの(アプリ)に自分を合わせるのでなく、自分の活動にあったアプリを作る。それがPC活用の基本なんじゃなかと思います。 そんな意見に同調していただける方向けにLinuxのDebianOSをはじめとした基本無料のアプリの使い方を紹介できたらなと考えています。

広告