【Angular】コンポーネント間のデータの受け渡し方法

どうも!大阪オフィスの西村祐二です。

SPAでサイトを作成するときにコンポーネント間でデータの受け渡しをしたい場面があると思います。

Angularでは@Output()@Input()を使うことでコンポーネント間のデータの受け渡しができます。

ただ、すこし使い方にクセがあるので備忘録も兼ねてブログにしておきたいと思います。

概念図

使い方のイメージとしては下記図となります。

親コンポーネントから子コンポーネントにデータを渡すときは@Input()を使います。
子コンポーネントから親コンポーネントにデータを渡すときは@Output()を使います。

環境

Angular CLI: 6.2.4
Node: 8.11.3
OS: darwin x64
Angular: 6.1.10
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.8.4
@angular-devkit/build-angular     0.8.4
@angular-devkit/build-optimizer   0.8.4
@angular-devkit/build-webpack     0.8.4
@angular-devkit/core              0.8.4
@angular-devkit/schematics        0.8.4
@angular/cli                      6.2.4
@ngtools/webpack                  6.2.4
@schematics/angular               0.8.4
@schematics/update                0.8.4
rxjs                              6.2.2
typescript                        2.9.2
webpack                           4.20.2

事前準備

プロジェクト作成

$ ng new output-input
$ cd output-input

コンポーネント作成

親コンポーネントと子コンポーネントを作成します。

  • 親コンポーネント
$ ng g c parent
  • 子コンポーネント
$ ng g c child

コンポーネントの紐づけ

  • root
<app-parent></app-parent>
  • 親コンポーネント
<p>
  親コンポーネント:
</p>
<app-child></app-child>
  • 子コンポーネント
<p>
  子コンポーネント:
</p>

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

今回、下記図のようにボタンをクリックすると、親コンポーネントで設定した文字列を子コンポーネントに渡し表示するというものをやってみようと思います。

  • 子コンポーネントの作業

親コンポーネントからデータを受け取るための設定をします。
今回はdataFromParentで親コンポーネントからデータを受け取るようにします。

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() dataFromParent: String;
  constructor() {}

  ngOnInit() {}
}
<p>
  子コンポーネント:{{dataFromParent}}
</p>
  • 親コンポーネント

ボタンをクリックすると変数に文字列がセットされて、子コンポーネントに渡す処理を記載します。

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
  public parentData: String;
  constructor() {}

  ngOnInit() {}
  onClick() {
    this.parentData = '親コンポーネントから文字列を渡します';
  }
}

<app-child [dataFromParent]='parentData'></app-child>[dataFromParent]が子コンポーネントへデータを送るためのインターフェイスになります。

<p>
  親コンポーネント:
</p>

<app-child [dataFromParent]='parentData'></app-child>
<input type="button" value="親コンポーネントから子コンポーネントへデータを渡す" (click)='onClick()' />

これで完成で、ボタンをクリックすると親コンポーネントで設定した「親コンポーネントから子コンポーネントへデータを渡す」という文字列が子コンポーネントで表示されるかと思います。

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

今回、下記図のようにボタンをクリックすると、子コンポーネントで設定した文字列を親コンポーネントに渡し表示するというものをやってみようと思います。

子コンポーネントから親コンポーネントにデータを渡す際は少しクセがありまして、実装としてはイベント経由でデータを渡すことになります。

  • 親コンポーネント

子コンポーネントにあるボタンをクリックした際に子コンポーネントからイベントを受け取る処理を記載します。
イベント経由するため今回はonReceiveEventFromChildで子コンポーネントからデータを受け取る関数を作成しています。

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

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
  public parentData: String;
  public childData: String;
  constructor() {}

  ngOnInit() {}
  onClick() {
    this.parentData = '親コンポーネントから文字列を渡します';
  }
  onReceiveEventFromChild(eventData: String) {
    this.childData = eventData;
  }
}

(event)="onReceiveEventFromChild($event)が子コンポーネントのイベントを受け取るためのインターフェイスになります。

<p>
  親コンポーネント:{{childData}}
</p>

<app-child [dataFromParent]='parentData' (event)="onReceiveEventFromChild($event)"></app-child>
<input type="button" value="親コンポーネントから子コンポーネントへデータを渡す" (click)='onClick()' />
  • 子コンポーネント

親コンポーネントへイベントを渡すための設定をします。
EventEmitterを使ってボタンクリック時にイベントを発生させ親コンポーネントにデータを送ります。

import { Component, OnInit } from '@angular/core';
import { Input } from '@angular/core';
import { Output, EventEmitter } from '@angular/core';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
  @Input() dataFromParent: String;
  @Output() event = new EventEmitter<String>();
  constructor() {}

  ngOnInit() {}
  onClick() {
    this.event.emit(
      '子コンポーネントから親コンポーネントへデータを渡す際はイベントを経由します。'
    );
  }
}

イベントを発生させるためのボタンを作成します。

<p>
  子コンポーネント:{{dataFromParent}}
</p>
<input type="button" value="子コンポーネントから親コンポーネントへデータを渡す" (click)='onClick()' />

これで完成で、ボタンをクリックすると子コンポーネントで設定した「子コンポーネントから親コンポーネントへデータを渡す際はイベントを経由します。」という文字列が親コンポーネントで表示されるかと思います。

さいごに

いかがだったでしょうか。

Angularでのコンポーネント間のデータの受け渡し方法についてまとめてみました。

誰かの参考になれば幸いです。

備考

<router-outlet>を使った場合はserviceクラスを使ってデータの受け渡しをするか、ngrxなどのステート管理する方法をとるしかなさそうです。

参考

https://teratail.com/questions/74779