GUI freezes until click event returns


#1

Hi!

I’m having som issues with a button in my Ionic app. My button have a click event “loginEvent()” that performs a login for the user. I have two span tags that is supposed to display a loading symbol while the login is performed.

The problem is that the button is not updated with the loading symbol until the loginEvent() returns. The click animation on the button does also not run until the loginEvent() returns.

Any idea why my button behaves like this?

Login button

<button ion-button block (click)="loginEvent();">
    <span *ngIf="!isLoading">Logga in</span>
    <span *ngIf="isLoading"><ion-spinner></ion-spinner></span>    
</button>

loginEvent()

loginEvent() {
    console.log("login");
    this.isLoading = true;
    this.userHandler.login(this.username, this.password, this);
    console.log("/login")
  }

#2

What is this.userHandler.login doing?


#3

It’s sending a request to Amzon cognito to authenticate the user


#4

This is using an atom bomb to kill a fly, so should only be done as an absolute last resort, but I recently ran into a similar problem with iOS’s implementation of WebCrypto key generation, and this was the only thing I could figure out to resolve the situation.

You can try injecting an instance of ApplicationRef and calling its tick() method right after you have changed the value of isLoading.

Upon further reflection, you may be able to get away with just injecting a ChangeDetectorRef and calling detectChanges() instead. I was using LoadingController to pop a loading indicator, so that was outside of my page’s realm, necessitating the application-wide tick.


#5

Thank you for your answer!

I tried to implement both the ApplicationRef with it’s tick() call and the ChangeDetectorRef. But I still got a 3-4 second delay until the GUI was updated with the loading symbol.


#6

That is very weird.

One thing that I have noticed in general is that Ionic components tend not to appreciate having their contents swapped out from underneath them. Instead of what you have now with one button and two sets of contents, can you try having two completely separate buttons with “isLoading/!isLoading” *ngIfs? The isLoading condition one probably doesn’t really need a (click) handler and maybe could be disabled as well, depending on your UI preference.


#7

That gives the same result as changing the contents of the button.

<button *ngIf="!isLoading" ion-button block (click)="doLogin()">Log in</button>
<button *ngIf="isLoading" ion-button block (click)="doLogin()">Loading..</button>
  1. I click the button, the click event is run until it sends the api call for authentication.
  2. The button is switched to the “Loading…” one after the api call is done (2 seconds after click)
  3. The view switches to the authenticated view after the api call is done and runs the callback