Angular4 以降でコンポーネント間をまたいだデータ連携を実現するサービスクラスを作る

Angular4 以降で、@Input@Output を使わず、コンポーネント間をまたいでデータのやり取りを行うためのサービスクラスを作った。

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { Subject } from 'rxjs/Subject';

/** 連携データのインターフェース */
interface DataEvent {
  /** 連携データを特定するキー */
  key: any;
  /** 連携するデータ */
  data: any;
}

/** コンポーネント間の情報の通知を行うサービス */
@Injectable()
export class DataService {
  /** Event */
  private event: Subject<DataEvent>;
  
  /** インスタンスを生成する */
  constructor() {
    this.event = new Subject<DataEvent>();
  }
  
  /**
   * データを送信する
   * 
   * @param key 連携データを特定するキー
   * @param data 連携するデータ
   */
  send(key: any, data: any): void {
    this.event.next({ key, data });
  }
  
  /**
   * キーに該当するデータを受信する
   * 
   * @param key 連携データを特定するキー
   */
  receive<T>(key: any): Observable<T> {
    return this.event.asObservable()
      .filter((event) => {
        return event.key === key;
      })
      .map((event) => {
        return event.data;
      });
  }
}

Angular におけるサービスクラスはシングルトンで動作するので、このサービスクラスをルートモジュールで provide しておき、サービスクラスでデータを保持するようにしておけば、配下のコンポーネントクラス同士でデータのやり取りができる、というワケ。

データを送りたい時は、データとそれを特定するキーを指定して send() メソッドを叩き、データを受信したい時はキーを指定して receive() メソッドを呼び、subscribe() しておけば、データが送られた瞬間に受け取ることができる。