Angularでカスタムコンポーネントの値受け渡しを理解するためのサンプルコード
Angular、TypeScript、Angular2-templateにおけるカスタムコンポーネントへの変数受け渡し
入力プロパティは、親コンポーネントから子コンポーネントへのデータ伝達に最も一般的な方法です。
方法
- 子コンポーネントの
@Input()
デコレータでプロパティを定義します。 - 親コンポーネントのテンプレートで、子コンポーネントの
<ng-component>
タグに[property]="value"
のようにバインディング属性を設定します。
例
子コンポーネント (message.component.ts)
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
})
export class MessageComponent {
@Input() message: string;
}
<app-message [message]="'Hello, Angular!'"></app-message>
コンテンツ投影は、親コンポーネントのテンプレート内の子コンポーネントの領域を定義し、その領域にコンテンツを挿入する方法です。
- 子コンポーネントの
<ng-content>
タグでコンテンツ挿入箇所を定義します。
<div class="card">
<ng-content></ng-content>
</div>
<app-card>
<h3>My Card</h3>
<p>This is some content.</p>
</app-card>
上記以外にも、@ViewChild
デコレータや EventEmitter
を用いた方法など、状況に応じてさまざまな方法があります。
補足
- Angular はバージョンによって API や機能が異なる場合があります。上記の例は Angular 14 をベースにしています。
- 上記はあくまで基本的な説明であり、より複雑な実装には他のテクニックが必要となる場合があります。
入力プロパティ
例:名前と挨拶を表示するコンポーネント
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
})
export class MessageComponent {
@Input() name: string;
get message(): string {
return `Hello, ${this.name}!`;
}
}
<app-message [name]="'Taro'"></app-message>
<app-message [name]="'Hanako'"></app-message>
出力:
Hello, Taro!
Hello, Hanako!
コンテンツ投影
例:見出しと本文を持つカードコンポーネント
<div class="card">
<h2><ng-content select="h2"></ng-content></h2>
<p><ng-content></ng-content></p>
</div>
<app-card>
<h2>My Card</h2>
<p>This is some content.</p>
</app-card>
<app-card>
<h2>Another Card</h2>
<p>This is another content.</p>
</app-card>
<div class="card">
<h2>My Card</h2>
<p>This is some content.</p>
</div>
<div class="card">
<h2>Another Card</h2>
<p>This is another content.</p>
</div>
上記はあくまで基本的な例であり、実際の開発では状況に応じてさまざまな方法を組み合わせて使用します。
- コンポーネントのスタイルは CSS ファイルで定義できます。
- コンポーネントロジックは TypeScript ファイルで記述できます。
- テストは Jasmine や Karma などのツールを使用して行うことができます。
Angular でカスタムコンポーネントに値を渡すその他の方法
サービスは、コンポーネント間でデータを共有するための方法です。コンポーネントはサービスを注入して、そのサービスのメソッドやプロパティにアクセスできます。
サービス (data.service.ts)
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataService {
private data: string = 'Hello, Angular!';
getData(): string {
return this.data;
}
setData(newData: string) {
this.data = newData;
}
}
import { Component, Input, OnInit } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
})
export class MessageComponent implements OnInit {
message: string;
constructor(private dataService: DataService) {}
ngOnInit(): void {
this.message = this.dataService.getData();
}
}
<app-message></app-message>
RxJS は、非同期データストリームを処理するためのライブラリです。コンポーネントは RxJS オブザーバブルをサブスクライブして、データストリームを購読できます。
import { Component, Input, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
})
export class MessageComponent implements OnInit {
message$: Observable<string>;
constructor() {
this.message$ = of('Hello, Angular!');
}
ngOnInit(): void {
this.message$.subscribe((message) => {
this.message = message;
});
}
}
<app-message></app-message>
URL パラメータを使用して、コンポーネント間でデータを渡すこともできます。
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
})
export class MessageComponent implements OnInit {
message: string;
constructor(private activatedRoute: ActivatedRoute) {}
ngOnInit(): void {
this.activatedRoute.queryParams.subscribe((params) => {
this.message = params['message'];
});
}
}
<a routerLink="/message?message=Hello, Angular!">Go to Message</a>
@ViewChild
デコレータを使用して、子コンポーネントのインスタンスを親コンポーネントから取得できます。その後、そのインスタンスのプロパティやメソッドにアクセスできます。
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
})
export class MessageComponent {
@Input() message: string;
@Output() messageChanged = new EventEmitter<string>();
onChange(newMessage: string) {
this.message = newMessage;
this.messageChanged.emit(newMessage);
}
}
<app-message #messageComponent [message]="'Hello, Angular!'"></app-message>
<button (click)="messageComponent.onChange('Hello, World!')">Change Message</button>
@ContentChildren
angular typescript angular2-template