Skip to content

Instantly share code, notes, and snippets.

@fracz
Last active Mar 2, 2017
Embed
What would you like to do?
Aurelia Promise Button

Aurelia Promise Button

A button that disables itself until the promise is resolved. See the provided animations below.

Default values work with Bootstrap and Font Awesome, but you can adjust it to your needs.

How to use?

Your template:

<template>
    <require from="path/to/promise-button"></require>
    <promise-button on-click.call="save()"
        waiting-text="Saving"
        success-text="Saved"
        failure-text="Error">
        Save me
    </promise-button>
</template>

And a component:

export class MyComponent {
  save() {
    return new Promise((resolve) => setTimeout(resolve, 2000));
  }
}
<template>
<button click.trigger="onButtonClicked()"
class="${stateBasedCssClass}"
disabled.bind="state == 'waiting'">
<span class="fa fa-fw ${stateBasedIcon}"></span>
<span show.bind="!stateBasedCaption">
<slot></slot>
</span>
<span if.bind="stateBasedCaption">${stateBasedCaption}</span>
</button>
</template>
import {bindable} from "aurelia-templating";
import {computedFrom} from "aurelia-binding";
export class PromiseButton {
@bindable onClick: () => any;
@bindable idleIcon = 'fa-save';
@bindable waitingIcon = 'fa-spinner fa-spin';
@bindable successIcon = 'fa-check';
@bindable failureIcon = 'fa-times';
@bindable waitingText;
@bindable successText;
@bindable failureText;
@bindable idleClass = 'btn btn-default';
@bindable waitingClass = 'btn btn-default';
@bindable successClass = 'btn btn-success';
@bindable failureClass = 'btn btn-danger';
@bindable resetTime = 2000;
private state = 'idle';
onButtonClicked() {
if (typeof this.onClick === 'function') {
this.state = 'waiting';
Promise.resolve(this.onClick())
.then(() => this.state = 'success')
.catch(() => this.state = 'failure')
.finally(() => this.resetStateAfterTimeout());
}
}
private resetStateAfterTimeout() {
setTimeout(() => this.state = 'idle', this.resetTime);
}
@computedFrom('state')
get stateBasedCaption() {
if (this.state == 'waiting' && this.waitingText) {
return this.waitingText;
} else if (this.state == 'success' && this.successText) {
return this.successText;
} else if (this.state == 'failure' && this.failureText) {
return this.failureText;
}
}
@computedFrom('state')
get stateBasedIcon() {
switch (this.state) {
case 'waiting':
return this.waitingIcon;
case 'success':
return this.successIcon;
case 'failure':
return this.failureIcon;
default:
return this.idleIcon;
}
}
@computedFrom('state')
get stateBasedCssClass() {
switch (this.state) {
case 'waiting':
return this.waitingClass;
case 'success':
return this.successClass;
case 'failure':
return this.failureClass;
default:
return this.idleClass;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment