Blog Content

    티스토리 뷰

    [Angular] 관계성이 없는 Component간의 통신

    관계성이 없는 Component간의 통신은 어떻게 할까?

    Service로 Data를 공유하자!


    siblings, grandchildren 등 직접적인 연결성이 부족한 Component간의 데이터 공유는

    Service를 사용하면 된다.


    그 중 RxJS를 이용해 데이터를 공유하는 방법이 있는데,

    BehaviorSubject를 사용하는 것이다.

    BehaviorSubject는 Observable의 특별한 형태인데,

    연관된 데이터를 쉽게 구독할 수 있는 method와

    데이터를 변경하기 위한 method등 사용하기 쉬운 몇가지 method를 제공하여

    보다 쉽게 RxJS기능을 이요할 수 있도록 고안된 class라고 한다.


    물론, RxJS에서 제공하는 Subject를 사용해도 되지만, BehaviorSubject를 선호하는 이유는 다음과 같다.

    1. BehaviorSubject는 구독 시 항상 현재값을 반환한다 -> onnext를 호출할 필요가 없다.

    2. raw data같은 마지막 값을 extract하기 위한 getValue() 함수를 가지고 있다.

    3. Component가 항상 최신 데이터값을 받는 것을 보장한다.


    예제는 다음과 같다.

    data.service.ts 에서 BehaviorSubject객체로 private 타입의 messageSource를 생성한다.

    Component에 의해 사용될 observable타입의 data stream을 처리하는 currentMessage 변수를 정의한다.

    마지막으로 changeMessage라는 이름의 함수를 만드는데,

    이는 값을 변경시키기 위해 BehaviorSubject객체에 있는 next를 call하는 함수이다.


    parent, child, sibling component는 모두 같은 방식으로 service를 사용한다.

    parent, sibling component의 ngOnInit()에 DataService 내에 선언된 currentMessage 값을 구독하여

    각 component에 선언된 message로 값을 할당받는다.


    값이 변경될 때는 DataService내의 changeMessage 함수를 호출하면

    새로운 데이터가 다른 모든 Component의 message 변수에 값이 자동으로 변경된다.

    data.service.ts

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    import { Injectable } from '@angular/core';
    import { BehaviorSubject } from 'rxjs';
    
    @Injectable()
    export class DataService {
    
      private messageSource = new BehaviorSubject('default message');
      currentMessage = this.messageSource.asObservable();
    
      constructor() { }
    
      changeMessage(message: string) {
        this.messageSource.next(message)
      }
    
    }
    


    parent.component.ts

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import { Component, OnInit } from '@angular/core';
    import { DataService } from "../data.service";
    
    @Component({
      selector: 'app-parent',
      template: `
        {{message}}
      `,
      styleUrls: ['./sibling.component.css']
    })
    export class ParentComponent implements OnInit {
    
      message:string;
    
      constructor(private data: DataService) { }
    
      ngOnInit() {
        this.data.currentMessage.subscribe(message => this.message = message)
      }
    
    }
    


    sibling.component.ts

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import { Component, OnInit } from '@angular/core';
    import { DataService } from "../data.service";
    
    @Component({
      selector: 'app-sibling',
      template: `
        {{message}}
        <button (click)="newMessage()">New Message</button>
      `,
      styleUrls: ['./sibling.component.css']
    })
    export class SiblingComponent implements OnInit {
    
      message:string;
    
      constructor(private data: DataService) { }
    
      ngOnInit() {
        this.data.currentMessage.subscribe(message => this.message = message)
      }
    
      newMessage() {
        this.data.changeMessage("Hello from Sibling")
      }
    
    }
    


    참고 사이트 : https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/

    Comments