Skip to content

Instantly share code, notes, and snippets.

@fracz
Last active March 2, 2017 12:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fracz/1536a2db1a2eb10ae7b8e41692a0a3ed to your computer and use it in GitHub Desktop.
Save fracz/1536a2db1a2eb10ae7b8e41692a0a3ed to your computer and use it in GitHub Desktop.
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