Skip to content

Instantly share code, notes, and snippets.

@ksol
Created December 12, 2014 15:19
Show Gist options
  • Select an option

  • Save ksol/db9118c38b0854da43ce to your computer and use it in GitHub Desktop.

Select an option

Save ksol/db9118c38b0854da43ce to your computer and use it in GitHub Desktop.
Ember.js: cancellable actions
import Ember from 'ember';
export default Ember.Controller.extend({
actionRunId: null, // This property stores the task id for our action
timerRunId: null, // this property stores the task id for the auto-updating of the timer
currentWaitTime: 0, // The timer (how many seconds are left until the action is executed)
waitTime: 5, // The delay (in seconds) during which you can cancel an action
cancelable: false, // Is there an action to cancel ?
cancelMessage: null, // The message to display to the user
// Note: `cancelable` could actually be derived from `currentWaitTime`,
// and be true when `currentWaitTime` > 0.
// This method updates the timer. It waits one second and then substracts 1 to the timer,
// thus retriggering itself. This goes on until the timer is at 0.
updateCurrentWaitTime: function() {
var _this = this;
// If the timer is > 0, wait a second and subtract one from it
if(this.get('currentWaitTime') > 0) {
var timerRunId = Ember.run.later((function() {
_this.set('currentWaitTime', _this.decrementProperty('currentWaitTime'));
}), 1000);
this.set('timerRunId', timerRunId);
// Otherwise, clear the task id and make sure there is no more task associated to it
} else {
if(!Ember.isBlank(this.get('timerRunId'))) {
Ember.run.cancel(this.get('timerRunId'));
this.set('timerRunId', null);
}
}
}.observes('currentWaitTime'),
// This method "enqueues" the given callback (your action) and wait
// x seconds before executing it, allowing you to cancel it
waitBeforeAction: function(callback) {
var actionRunId;
var self = this;
var delay = this.get('waitTime') * 1000;
// Starting now, there's an action waiting to be executed, meaning we can cancel it.
// We're setting the timer here, and this triggers the observer above.
this.setProperties({
cancelable: true,
currentWaitTime: this.get('waitTime')
});
// Keepking track of the "task id". Necessary to cancel it later
actionRunId = Ember.run.later((function() {
// At this point, we're executing the action, so there's nothing that can be canceled.
self.setProperties({
cancelable: false,
cancelMessage: null
});
// Executing the callback in the context of the controller
callback.call(self);
}), delay);
this.set('actionRunId', actionRunId);
},
actions: {
// This is a regular action, executed right away
someAction: function() {
// ...
},
// This action handles the cancel logic
cancelAction: function() {
// Resetting the properties here
this.setProperties({
cancelable: false,
currentWaitTime: 0,
cancelMessage: null,
});
// Cancelling the action in the run loop, clearing the saved ID
if(!Ember.isBlank(this.get('actionRunId'))) {
Ember.run.cancel(this.get('actionRunId'));
this.set('actionRunId', null);
}
},
// Assignment: accept/refuse logic
importantAction: function() {
this.set('cancelMessage', 'You just did something that can cancel');
this.waitBeforeAction(function() {
// Your action logic goes here
});
},
}
});
{{!-- Your template here... --}}
{{#if cancelable}}
<p>
<strong>{{cancelExplanations}}</strong>
</p>
<p class="text-important">
You're going to do something important. If this was a mistake, you have
<strong>{{currentWaitTime}}</strong>
second(s) to cancel with the button below.
</p>
<button type="button" class="big-button" {{action "cancelAction"}}>
Yes, I want to cancel
</button>
{{/if}}
{{!-- Your template here... --}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment