6

While working on Ionic 3 app I have faced problem that when you subscribe to observable from service in ngOnInit and update a local variable into it, it does not update the view.

For e.g HTML template <p>{{myVariable}}</p>

constructor(myService: MyService) {
}
ngOnInit() {
  this.myService.myObservable.subscribe((data) => {
    this.myVariable = data;
  });
}

But when you do same thing from constructor, it works.

contructor(myService: MyService) {
  this.myService.myObservable.subscribe((data) => {
    this.myVariable = data;
  });
}

Its an Ionic 3 app. It contains different Ion Tabs. The problem is that the view is not updated automatically when you subscribe in ngOnInit. You have switch between tabs for it to work. But when you subscribe in constructor it works without needing to switch tab.

Any idea why this is happening. Any hints will be appreciated. Thanks.

BeeBee8
  • 2,944
  • 1
  • 27
  • 39
  • because in constructor , service is injected so it's directly injecting to service to component ,in the `ngOnInit()` it's not happening.. – Ganesh Aug 16 '18 at 12:03
  • 1
    can you show the an example in [stackblitz](https://stackblitz.com/). There is no reason why it wouldnt work in ngOnInit – Suraj Rao Aug 16 '18 at 12:28
  • How do you emit your observable data from service? Can you add that code? – Amit Chigadani Aug 17 '18 at 04:15
  • In ionic`ngOnInit` I believe only gets called once, initially when the view is navigated to. The constructor, on the other hand, seems to always get called. – alphapilgrim Nov 14 '19 at 18:00
  • @alphapilgrim The constructor is not always getting called - it's a constructor. It is called exactly once per component instance (and the construction is outside of the Angular lifecycle). – Jason Long Jul 15 '21 at 23:09

2 Answers2

2

It has to do with Angular change detection, for more info about this, read: Angular Change detection.

You should use Angular ngZone service to solve this, it will update the view.

import { Component, NgZone } from "@angular/core";

constructor(
    private ngZone: NgZone
    ...
){ }

...
ngOnInit() {
    this.myService.myObservable.subscribe((data) => {
        this.ngZone.run(()  => {
            this.myVariable = data;
        });
    });
}
isAif
  • 2,126
  • 5
  • 22
  • 34
theriddle2
  • 398
  • 3
  • 9
0

You do not clarify what kind of observable you have (e.g. 'cold', 'hot', Subject, BehaviorSubject, an HttpClient observable, etc.). If it is an observable that you have created yourself, it may well be that its value changed before you subscribe to it in the ngOnInit method and therefore depending on the type of observable the value is lost. Since the service that created the observable is injected in the constructor, the constructor gets earlier access to whatever value may be emitted by the service. If you are constructing the observable yourself, consider using a BehaviorSubject:

What is the difference between Subject and BehaviorSubject?

AsGoodAsItGets
  • 2,886
  • 34
  • 49
  • Thanks for your input, I had already used `BehaviourSubject` I'm getting the observable subscription correctly, but problem is with angular change detection, somehow when I subscribe in the ngOnInit it goes out of angular zone and it is unable to detect changes. – BeeBee8 Jan 30 '19 at 17:33