Search code examples
angularasynchronousbuttonuser-experience

Holding a button state until a promise is resolved in Angular 9


In my opinion, web applications have the drawback that they feel "fake" to the user, in the sense that when clicking a button it doesn't really give the impression that something is happening. This is because the operation usually is ran asynchronously, and the button can be pressed multiple times, unless some overlay is implemented (which is kinda ugly).

My aim is to design some way to hold the button as "pressed" until the underlying async operation is resolved (or rejected), basically having the button component wait until the operation finishes. This is also what happens in normal desktop applications most of the times.

The idea is to implement it as a directive or something that intercepts the click() event (or a custom one like onClick()), and if the called method returns a promise, then wait until the promise is resolved to make the button usable again.

<button (click)="hello()">Hello</button>
async hello(): Promise<void> {
  // Do stuff...

  return Promise.resolve();
}

To make the idea clearer, this is what normally happens:

User action:             hover    click     release
Button state:    normal  :hover   :active   normal
Triggers:                         hello()                resolve()

And what I'm aiming for:

User action:             hover    click     release
Button state:    normal  :hover   :active             -> normal
Triggers:                         hello()                resolve()

Any help is appreciated, thanks.


Solution

  • I initially created a hacky solution that had issues when functions referred to injected parameters, then I found an example that's exactly what I needed:

    angular-async-await-click

    Hope it could come useful to others.