Angular4にて、サービスを介してコンポーネントからコンポーネントへ値を送る
コンポーネントから別のコンポーネントに値を送る
親子関係があるときは、@Input()を使用することにより親から子へ値を送りました。
今回、あるコンポーネントから親子関係にないコンポーネントへ、
サービスを介して値を送る実装をしてみたいと思います。
- コンポーネントから別のコンポーネントに値を送る
- 解説
- 0. 準備
- 1. componentA, componentB, SendValueServiceを作成
- 2. SendValueServiceにてSubjectを読み込む
- 3. SendValueServiceにprivateの口を追加
- 4. SendValueServiceにpubilcの耳を追加
- 5. app.moduleににSendValueServiceをDIする
- 6. compBのコンストラクタにSendValueServiceを記述
- 7. pubilcの耳を澄まさせる(subscribe)
- 8. SendValueServiceに喋りを実行するメソッドを追加
- 9. compAのコンストラクタにSendValueServiceを記述し、喋らせるメソッドを追加
- 10. componentAのtemplateにボタンを追加
- 結果
解説
具体的な手順に入る前に、大体の流れを確かめておきましょう。
今回やりたいことを図にすると、こんな感じになります。
Serviceを介して、ComponentAからComponentBへMessageを送る感じです。
これを実現するために、まずServiceクラス内に「privateの口」「publicの耳」を用意します。
次に、ComponentBにpublicの耳を配置します。
この時、耳を澄ませておくことが重要です(subscribe)
これで準備が整いました。
まず、ComponentAがServiceに以下のように依頼します。
次に、Serviceがこんにちは!と叫びます。
そうすると、耳を澄ませていたComponentBに聞こえます。
なにいってんだこいつ、という感じだと思いますので、
実際にコードを見て確認してみましょう。
0. 準備
新規プロジェクトを作成し、サーバをスタートさせます。
ng new send-value ng serve
1. componentA, componentB, SendValueServiceを作成
ng g component comp-a ng g component comp-b ng g service send-value
2. SendValueServiceにてSubjectを読み込む
// send-value.service.ts import { Subject } from 'rxjs/Subject';
3. SendValueServiceにprivateの口を追加
// send-value.service.ts private toCompBDataSource = new Subject<string>();
4. SendValueServiceにpubilcの耳を追加
// send-value.service.ts public toCompBData$ = this.toCompBDataSource.asObservable();
5. app.moduleににSendValueServiceをDIする
// app.module.ts import { SendValueService } from './send-value.service'; // 追加 @NgModule({ providers: [SendValueService], // 追加 })
SendValueServiceをDIするのはapp.moduleのみです。
compA, compBにもDIしてしまうと、
3つの別々のSendValueServiceインスタンスが出来てしまうので、うまく動きません。
サービスを使ってコンポーネント間で値のやり取りをするときは、
「同一のServiceインスタンス」を介して値のやり取りができるように注意しましょう。
今回はmoduleにDIしていますが、2つのコンポーネントが同一の親を保つ場合は、
その親にDIしてもOKです。
6. compBのコンストラクタにSendValueServiceを記述
// comp-b.component.ts import { SendValueService } from '../send-value.service'; // 追加 export class CompBComponent implements OnInit { constructor( private sendValueService :SendValueService // 追加 ) { } ngOnInit() { } }
7. pubilcの耳を澄まさせる(subscribe)
// comp-b.component.ts import { Subscription } from 'rxjs/Subscription'; // 追加 export class CompBComponent implements OnInit { private subscription: Subscription; // 追加 constructor( private sendValueService :SendValueService ) { } ngOnInit() { /** ここから */ this.subscription = this.dataService.toCompBData$.subscribe( msg => { console.log('compBは' + msg + 'をうけとりました'); }); } /** ここまで追加 */ }
8. SendValueServiceに喋りを実行するメソッドを追加
// send-value.service.ts public sendMessageToCompB(msg) { this.toCompBDataSource.next(msg); // 喋る }
9. compAのコンストラクタにSendValueServiceを記述し、喋らせるメソッドを追加
// comp-a.component.ts import { SendValueService } from '../send-value.service'; export class CompAComponent implements OnInit { constructor( private sendValueService :SendValueService // 追加 ) { } /** ここから */ onClick() :void { this.sendValueService.sendMessageToCompB('こんにちは!'); } /** ここまで追加 */ }
10. componentAのtemplateにボタンを追加
// comp-a.component.html <button (click)="onClick()">クリックしてね</button>
結果