Search code examples
angularrxjsobservablebehaviorsubject

Sharing data between muliple components - issue due to object references


I'm implementing a data store service to share data between multiple sibling components. Each components needs to get notified about changes in the data store. The data store does not populate itself, the data needs to be set from a controller.

data.store.ts

@Injectable()
export class DocumentIssueStore {

  private _documentIssue: BehaviorSubject<DocumentIssueModel>;

  constructor() {
    this._documentIssue = new BehaviorSubject(null);
  }

  public setValue(newVal: DocumentIssueModel) {
    this._documentIssue.next(cloneDeep(newVal));
  }

  public documentIssue(): Observable<DocumentIssueModel> {
    return this._documentIssue.asObservable();
  }

  public current(): DocumentIssueModel {
    return cloneDeep(this._documentIssue.getValue());
  }

In the ngInit methods of both components, i subscribe to the data store:

// Subscribe to changes in the store
this.storeSubscription = this.documentIssueStore.documentIssue().subscribe(
  (data: DocumentIssueModel) => {
    this.documentIssue = data;
  }
);

The problem: Changing this.documentIssue in any component leads to:

  • Changing the instance (this.documentIssue) in all other components subscribed
  • Changing the instance in the store (this._documentIssue.getValue())

The goal: - Having seperate objects in the components, which can be changed and then send to the store by calling the setValue method


Solution

  • Each subscriber could clone the data if they intend to modify it:

    // Subscribe to changes in the store
    this.storeSubscription = this.documentIssueStore.documentIssue().subscribe(
      (data: DocumentIssueModel) => {
        this.documentIssue = cloneDeep(data);
      }
    );