4

In the Internet I found such example how to sharing data with a service:

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

@Injectable()
export class DataService {

  private subject = new Subject<any>();

  sendData(phone: any) {
    this.subject.next(phone);
  }

  clearData() {
    this.subject.next();
  }

  getData(): Observable<any> {
    return this.subject.asObservable();
  }

}

Then we subscribe to changes

subscription: Subscription;

this.subscription = this.dataService.getData()
  .subscribe(data => {
     this.someData= data;
  });

Ok, this work fine. But if I want to share more than one element? It seems unreasonable to copy this code for every element, changing only the name. But I can't find any abstract solutions. Maybe using map with the names and the data itself, but I can't understand how to subscribe to changes in this case and how should look like the service.

ch.45
  • 75
  • 1
  • 7

2 Answers2

8

To achieve this you can put all relevant values into a wrapper object an this object in the (Behavior)Subject. Every Subscriber changes the content(s) of its personal value(s) of interest and writes then the whole wrapper back.

e.g.

Let say you put all models you define into models.ts. Here's the wrapper.

export class MyWrapper {
   constructor(
      public value1?: string,
      public value2?: number,
      public value3?: boolean
   ){}
}

Then you import this wrapper model into your Service and all Subscribers

import { Injectable } from '@angular/core';
import {Subject} from 'rxjs/Subject';
import {Observable} from 'rxjs/Observable';
import { MyWrapper } from '../models/models';

@Injectable()
export class DataService {

  private subject = new Subject<MyWrapper>();

  sendData(wrapper: MyWrapper) {
    this.subject.next(wrapper);
  }

  clearData() {
    this.subject.next();
  }

  getData(): Observable<MyWrapper> {
    return this.subject.asObservable();
  }

}

And in one of the Subscribers, no matter whether it's a Service, Directive or Component, you can manipulate the value. Just an example! There are many different ways how to handle the wrapper back and forth.

import { MyWrapper } from '../models/models';

private localWrapper: MyWrapper;

constructor(
 private dataService: DataService
){}

ngOnInit(): void {
   this.dataService.getData().subscribe(wrapper => {
      this.localWrapper = wrapper;
   });
}

// The wrapper in your service gets replaced and all subscribers
// get a fresh version of all contained values. This way you
// could exchange hundreds of values with only one set of methods
// and a single (Behavior)Subject.
private saveValue1(value: string): void {
   localWrapper.value1 = value;

   this.dataService.sendData(localWrapper);
}
1

i think the solution you are searching for is similar to ngrx library. what you want to do in this case is make an object with different layers of data(phones,addresses,names etc) and throw it into BehaviorSubject.Every subscriber can then extract necessary layer of information by using Pluck operator of rxjs.if you want to change certain layer of data you have to make use of immutable data change by applying spread operator and changing only the layer you need while other layers stay intact.