[Angular]コンポーネント間でデータを受け渡す ~InputとOutput編~


復習がてら + Angular v9 を試しながら書いてます。

親子コンポーネント間のデータの受け渡しを行う。

Angularプロジェクトの立ち上げから丁寧にやっていく。

環境

  • Angular: v9.0.4
  • Node: v12.16.1
  • OS: win32 x64

準備:Angularプロジェクト作成 ~ 親子Conponent作成 まで

プロジェクト作成、コンポーネント作成のやり方はAngular公式ドキュメントを確認すればOKなのでコマンドだけのせとく。


# 新規プロジェクト作成
ng new {プロジェクト名}

# 念のため v9(現時点の最新版) にあげとく
ng update @angular/core @angular/cli

# コンポーネント作成 分かりやすいように親:parentと命名
ng generate component parent

# コンポーネント作成 分かりやすいように子:childと命名
ng generate component child

app.component.htmlのテンプレート消して作成したcomponentをのっける

コンポーネント紐づけ

  • root
app.component.html
<app-parent></app-parent>
  • 親コンポーネント
parent.component.html
<p>吾輩が親コンポーネントである。</p>
<app-child></app-child>
  • 子コンポーネント
child.component.html
<p>私は子コンポーネントです。</p>

確認。

ng serve -o

Input編

親コンポーネントで設定した文字列を子コンポーネントに渡してみよう。

子コンポーネント側で親から値を受け取る準備をする

  • 子コンポーネント側
child.component.ts
import { Component, OnInit } from '@angular/core';
import { Input } from '@angular/core';  // 追加
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
  @Input() valueFromParent: string;  // 追加
  constructor() { }

  ngOnInit(): void {
  }
}
child.component.html
<p>
    私は子コンポーネントです。
    親から受け取った値:{{valueFromParent}}
</p>

親コンポーネントから子に値を渡す

親コンポーネントにあるテキストボックスに値を入力したら子コンポーネントに値を渡す。

  • 親コンポーネント側ですること:
    • テキストボックスをHTMLに置く
    • 入力イベント用意
    • データを送れるように設定する
parent.component.html
<p>吾輩が親コンポーネントである。</p>

<div>
  子に渡したい値:
  <input type="text" (keyup)="inputValue($event)">
</div>

<app-child [valueFromParent]="toChildValue"></app-child>
parent.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
  public toChildValue: string; // 子へ送る値を格納する変数を用意
  constructor() { }

  ngOnInit(): void {
  }

  inputValue(event: any) { // without type info
    this.toChildValue = event.target.value;
  }
}

完成。

テキストボックスに値を入力すると、keyupに設定したinputValue()メソッドが呼び出される。

keyup:ユーザーがキーを押して離すのがトリガー。

※changeイベントでも代用できるよ。

inputValue()では親コンポーネントのパブリック変数 toChildValue に入力値を代入している。

parent.component.html
<app-child [valueFromParent]="toChildValue"></app-child>

子コンポーネントで設定した変数 valueFromParentに toChildValueを設定することで、子に値を渡せる。

Output編

Outputは子から親に値を返す。

イメージとしては、親が子のイベントを監視する感じ。

子コンポーネントで入力した値を親コンポーネントに返そう。

EventEmitter使います。初めて使う方はこちら→ https://www.whizz-tech.co.jp/1659/ 見ながらのほうが分かりやすくなると思います。

  • 親コンポーネント側
    • 子供のイベントを監視するようにする
parent.component.html
<p>
  吾輩が親コンポーネントである。子から受け取った値:{{fromChildValue}}
</p>

<div>
  子に渡したい値:
  <input type="text" (keyup)="inputValue($event)">
</div>

<app-child [valueFromParent]="toChildValue"
           (event)="onReceiveEventFromChild($event)">
</app-child>
parent.component.ts
  public fromChildValue: string; // 子から受け取った値を格納する変数を用意

  onReceiveEventFromChild(eventValue: string) {
    this.fromChildValue = eventValue;
  }
  • 子コンポーネント側
    • Output()デコレータ用意。
    • EventoEmitterインスタンス化。
    • inputこのメソッドinputChildValue()を呼び出す
    • inputChildValue()内で親に返したい値を引数にしてemitメソッドを呼び発火させる。
child.component.html
<p>
    私は子コンポーネントです。
    親から受け取った値:{{valueFromParent}}
</p>

<!-- ↓追加 -->
<div>
    親に渡したい値:
    <input type="text" (keyup)="inputChildValue($event)">
</div>
child.component.ts
import { Component, OnInit } from '@angular/core';
import { Input, Output, EventEmitter } from '@angular/core';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
  @Input() valueFromParent: string;
  @Output() event = new EventEmitter<string>(); // 追加
  constructor() { }

  ngOnInit(): void {
  }

  // 追加
  inputChildValue(event: any) {
    this.event.emit(event.target.value);
  }

}

完成。

 子側では、イベントが発火したよとういうのをOutputしてるイメージ。

親側は、子のイベントを常に監視しているイメージ。
イベントが発火したらonReceiveEventFromChildメソッドを呼び、親の変数に受け取った値を代入している。

終わり

次は@ViewChild&AfterViewInitを使ったデータの渡し方について復習する予定。

使いこなせば自在に子コンポーネントを参照し、親コンポーネント内の変数にアクセスできるようになるだろう。

  • @ViewChild
  • AfterViewInit

参考