Sledge
Sledge

Reputation: 1345

How to react to change in Angular <2.x observable

I have a data service component that is intended to share a BehaviorSubject class variable between a few components.

I have the service set up as such:

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

@Injectable()
export class SharedStateService {
  private selectedYearMo = new BehaviorSubject('2018-11');
  yearmo = this.selectedYearMo.asObservable();

  constructor() { }

  changeYearmo(yearmo: string) {
    this.selectedYearMo.next(yearmo);
    this.yearmo = this.selectedYearMo.asObservable();
    console.log("yearmo change request recieved at service");
    console.log("yearmo changed: ", this.yearmo);
  }

  getYearmo(){
    return this.yearmo;
  }
}

Each of the components implements the subscription to the observable as follows:

...
constructor(private sharedStateService: SharedStateService) {
};
...
getYearMo(): void {
    this.sharedStateService.getYearmo().subscribe(
      (yearmo: any) => {
        console.log("BehaviourSubject test received "+yearmo+" at component.");
        this.cd.markForCheck();
      }
    );
  }
...
ngOnInit() {
  this.getYearMo();
  this.getData();
};
...
ngOnChanges(changes: SimpleChanges) {
    console.log("detected changes...");
    for (let propName in changes) {
        let change = changes[propName];
        let curVal  = JSON.stringify(change.currentValue);
        let prevVal = JSON.stringify(change.previousValue);
      console.log(curVal);
      console.log(prevVal);
    }
  };
...

Right now, when the observable changes, the log message defined in getYearmo appears as expected BehaviourSubject test received "+yearmo+" at component but thte ngOnChanges() method is never called. However, I would like a way to handle this sort of things in a proper lifecycle hook like ngOnChanges() since eventually I might want to have more than one subscription.

Is there another way to react to changes in my observable that I'm missing? It seems like this would be a common thing to do but I'm having trouble understanding from the resources I've come across thus far.

Upvotes: 1

Views: 1951

Answers (1)

CozyAzure
CozyAzure

Reputation: 8468

I think you are confused with the reactive property of Observables and the ngOnChanges lifecycle hook of Angular.

ngOnChanges- as per the documents, is a lifecycle hook aka a callback function that will be called if you have any data bound input properties - that is - properties that is decorated using @Input in your Angular. It is NEVER used to detect any changes of your Observables.

Respond when Angular (re)sets data-bound input properties. The method receives a SimpleChanges object of current and previous property values.

Called before ngOnInit() and whenever one or more data-bound input properties change.

Assuming you are following the Angular docs (which can be seen that your code is almost as exactly as the doc's exammple), you can see that their code has properties that is decorated using @Input.

@Input() hero: Hero;
@Input() power: string;

And that this two properties are actually being "passed into" the component through data-binding, using the square brackets:

<on-changes [hero]="hero" [power]="power"></on-changes>

So no, ngOnChanges is NOT the place you want to write your code to react to your Observable changes. It is there for you to write your code to react to the @Input changes. Observable's subscribe is already there for you to implement whatever you want in the event the Observables emit an emission. And to subscribe to your Observabels, yes, the best place to do it as ngOnInit lifecycle hook.

Upvotes: 2

Related Questions