How to call a function when changes the value of a variable?


#1

I’d like to call the functions that use web services to populate the pages of my App only after that a certain function has terminated.
This function makes some checks and sets to true the variable: isWsAvailable.

Now in all the pages of my app, I’m calling the web services in the ionViewDidLoad method but it is executed when isWsAvailable is still false.

So, is it possible to make sure that a function is called only when isWsAvailable changes its value to true?

thank you

cld


#2

I hope I do understand your question right. But this seems like a simple if else situation.

As example:

ionViewDidLoad(){
  if(isWsAvailable == true){
    //execute a function
  }
}

(Or are you aiming on a realtime change when the Page is already loaded ?)


#3

I have to fill the page when isWsAvailable becames true.
So I have to wait this change.
With your code if isWsAvailable is false when I make the check the first time I will never fill the page.


#4
  1. Make your isWsAvailable a BehaviorSubject.
  2. Subscribe to that BehaviorSubject.
  3. Make your ‘trigger’ update that isWsAvailable object when your state a.k.a. isWsAvailable is ‘ready’.
  4. Unsubscribe when done using and/or leaving the view.
import { BehaviorSubject } from "rxjs/Rx";
...
public isWsAvailable: BehaviorSubject<boolean> = new BehaviorSubject(false);
...
constructor(){
// OR
ionViewDidLoad(){
    ...
    // this subscription will trigger EVERY time you update isWsAvailable
    this.isWsAvailable.subscribe((value) => { 
       console.log(value);
       if (true === value) {
           // do some stuff
       } else {
           // do some other stuff
       }
    });
    ....
}

public ionViewDidLeave() {
    ...
    this.isWsAvailable.unsubscribe();
    ...
}

You can update your isWsAvailable and trigger it like this:

    ....
    // your incoming trigger || functions ready
    this.isWsAvailable.next(true);
    ....

P.s.; code not tested; use as refference


#5

Thank you @bilow it is a very interesting solution, I didn’t know the existence of BehaviourSubject, it seems very useful.

cld


#6

I consider this a brittle and problematic design. Pages should not care about network minutia like this. All of this isWsAvailable stuff should be completely contained within the service provider. It should be returning Observables. Those Observables can arrange to wait as necessary, but their consumers should not be aware of any of it.


#7

Yes, I’m writing this code in a provider (WsManager) that manages all the calls to the REST web services.
This provider is used by all the pages of the app in the ionViewDidLoad event of each one.

Now the fact is that the data used by this Provider to call the web services (URL, username, password, etc) come from an Electron page through an IPC and it seems that they are not immediately available even in the constructor of the Provider.
So I have to wait for the Electron data to call the web service, and the result of the web service to fill the page.
isWsAvailable tells to me that the Electron data have arrived.

However looking at BehaviorSubject they seem to me that they work in a similar way to the Observables you are talking about.


#8

I did something similar as described. In the html, I want to enable/disable the submit button under 3 conditions
(1) when the user selects at least 1 role
(2) when a captcha control has been verified
(3) when all items on a form are validated

In the html
<button ion-button round end favorite type=“submit” [disabled]="!formValid">Create Account

In the typescript file
captcha: boolean = false;
formValid: boolean = false;
roleCount: number = 0;

// sign up to be notified of changes to control variables
ngOnInit() {
this.onChanges();
}

onChanges(): void {
this.userForm.valueChanges.subscribe(data => {
this.formValid = this.captcha && this.userForm.valid && (this.roleCount > 0);
});
}

onResponse(response) {
this.captcha = true;
this.formValid = this.captcha && this.userForm.valid && (this.roleCount > 0);
}