みなさんこんにちは、現役エンジニアのサメハックです
アパレル企業でトップ販売員を経て
未経験からWebエンジニアに転職し、
現在正社員として5年働いています!
Angularの解説シリーズです。
今回は子コンポーネントに値を渡す方法について学んでいきましょう!
駆け出しエンジニアや未経験の方、
また新入社員を指導する先輩社員にとっても
わかりやすいように解説していきます!
- 子コンポーネントに値が渡せる
※PCにnpm、nodeがインストールされている前提で記述します。
yarn等をお使いの方は読み替えてください。
作りたいもの
ユーザ名が表示されたボタンをクリックすると、
選択したユーザの情報が表示されるアプリケーションを作ります。
★Vue.jsやReactでいうところのpropsを渡す処理です。
他のファイルは左上のハンバーガーメニューをクリックして確認してね!
親コンポーネントから子コンポーネントへデータを渡す
親コンポーネントの設定
親コンポーネントから子コンポーネントへデータを渡すには、
子コンポーネント内のタグで以下のような記述をする必要があります。
<子コンポーネント [子コンポーネントへ渡す際のプロパティ名]="渡したいデータ"></子コンポーネント>
子コンポーネントの設定
データを受け取るには、@Inputデコレータを設定する”だけ”です。
import { Input } from '@angular/core';
@Input() 親から受け取るプロパティ名: データ型;
親子でプロパティ名が違う場合
<子コンポーネント [propsX]="データ"></子コンポーネント>
import { Input } from '@angular/core';
@Input(propsX) 子コンポーネントで扱いたいプロパティ名: データ型;
子コンポーネントに値を渡そう!
インターフェイスの作成
親子どちらのコンポーネントでも使用できるように、
外部ファイルにインターフェイスを設定します。
touch ./src/app/user-detail.ts
user-detail.ts
// ユーザ情報を定義
export interface UserDetail {
name: string;
age: number;
job: string;
hobby: string;
}
interfaceについて詳しく知りたい方はこちら!
親コンポーネントの作成
ng generate component users
users.component.ts
import { Component, OnInit } from '@angular/core';
import { UserDetail } from '../user-detail';
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.css'],
})
export class UsersComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
// 選択されたユーザー ※子コンポーネントに渡す値
selectedUser: UserDetail;
/**
* クリックされたユーザ情報をthis.selectedUserに入れて子コンポーネントに渡す
* @param user ユーザ情報
* 戻り値なし
*/
userSelect(user: UserDetail): void {
this.selectedUser = user;
}
// Userインターフェイスを型として指定
user1: UserDetail = {
name: 'サメハック',
age: 29,
job: 'エンジニア',
hobby: 'ギター',
};
// Userインターフェイスを型として指定
user2: UserDetail = {
name: 'いぬハック',
age: 30,
job: '不動産',
hobby: 'ランニング',
};
// Userインターフェイスを型として指定
user3: UserDetail = {
name: 'ねこハック',
age: 45,
job: 'アパレル',
hobby: '旅行',
};
userList = [this.user1, this.user2, this.user3];
}
ここでのポイントは、この部分です。
// 選択されたユーザー ※子コンポーネントに渡す値
selectedUser: UserDetail;
/**
* クリックされたユーザ情報をthis.selectedUserに入れて子コンポーネントに渡す
* @param user ユーザ情報
* 戻り値なし
*/
userSelect(user: UserDetail): void {
this.selectedUser = user;
}
クリックイベントを検知した際に、データを渡すため
selectedUserというプロパティを定義し、
クリックされた際に選択されたユーザデータをselectedUserにセットします。
users.component.html
<!-- ループ処理でuserListを1つずつ取り出す -->
<div *ngFor="let user of userList">
<!-- クリックされたら、userSelect関数を叩き、引数としてuserデータを渡す -->
<button (click)="userSelect(user)">{{ user.name }}</button>
</div>
<br />
<!-- 子コンポーネントのuserプロパティにselectedUserを渡す -->
<app-user-detail [user]="selectedUser"></app-user-detail>
ループ処理とクリックイベントリスナーについて復習したい方はこちら!
子コンポーネントの作成
ng generate component user-detail
user-detail.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { UserDetail } from '../user-detail';
@Component({
selector: 'app-user-detail',
templateUrl: './user-detail.component.html',
styleUrls: ['./user-detail.component.css'],
})
export class UserDetailComponent implements OnInit {
/**
* 親コンポーネントから値を受け取るための記述
* @Input() プロップス名: データ型;
*
* UserDetail型のデータをuserというプロップス名で受け取る
*/
@Input() user: UserDetail;
constructor() {}
ngOnInit(): void {}
}
あとは受け取ったuser好きに画面に表示しよう!
user-detail.component.html
<div *ngIf="user; else notSelect">
名前:{{ user.name }}
<br />
年齢:{{ user.age }}
<br />
職業:{{ user.job }}
<br />
趣味:{{ user.hobby }}
</div>
<ng-template #notSelect>ユーザを選択してください</ng-template>
ちなみに、このように受け取ったデータを元に表示を行う場合
*ngIfの設定はほぼ必須です。
この設定をなくしてしまうと、一見正しく表示されますが、
{{ user.name }}のuserが未定義なので
ERROR TypeError: Cannot read properties of undefined (reading 'name')
というエラーがコンソールに出てしまいます。
画面に反映させよう!
app.component.html
<app-users></app-users>
まとめ
- 親コンポーネント.htmlの設定
- <子コンポーネント [子コンポーネントへ渡す際のプロパティ名]=”渡したいデータ”>
- 子コンポーネント.tsの設定
- @Input() 親から受け取るプロパティ名: データ型;
満足いただけたら、1クリックなのでSNSフォローしてもらえると嬉しいです🦈