Skip to content

Instantly share code, notes, and snippets.

@Genkilabs
Last active January 3, 2016 03:49
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Genkilabs/8404456 to your computer and use it in GitHub Desktop.
Save Genkilabs/8404456 to your computer and use it in GitHub Desktop.
Debounced Autosave for EmberJS using 1.2.0-beta.4 and EmberData 1.0.0-beta.4+canary.3993001d with hooks for pacifier from http://ricostacruz.com/nprogress
// Debounced autosave for Ember.js
// Original code by Mitch Lloyd http://gaslight.co/blog/?author=mitchlloyd
// updated from http://gaslight.co/blog/an-autosave-pattern-for-ember-and-ember-data
// repo at https://github.com/gaslight/ember-autosaving
// Changed to work with latest Ember Data as of 2013-12-16 by Genkilabs
// Includes hooks for pacifier from http://ricostacruz.com/nprogress
// NOTE: This requires a 2 part install in which the controller and any models it loads have the corresponding mixin
// This is how long we will wait on a form before saving. I like to put this in App.AUTOSAVE_DELAY
var AUTOSAVE_DELAY = 1500
// Model Component
App.AutosavableModel = Ember.Mixin.create({
_buffers: function(){
return Ember.Map.create()
}.property(),
});
// Controller Component
App.AutosavableController = Ember.Mixin.create({
bufferedFields: [],
instaSaveFields: [],
// Convenience property to access all the fields together
_allFields: function() {
return this.get('bufferedFields').concat(this.get('instaSaveFields'));
}.property(),
// # If we update a field that has been specified as one of the
// # bufferedFields or instaSaveFields write these to a buffer
// # instead of the actual attribute and save.
setUnknownProperty: function(key, value) {
if (this.get('bufferedFields').contains(key)) {
this.get('_buffers').set(key, value);
return this._debouncedSave();
} else if (this.get('instaSaveFields').contains(key)) {
this._super(key, value);
return this._save();
} else {
return this._super(key, value);
}
},
// Pull properties from the buffer if they have been set there.
// This is like the getter for our buffer or the model
unknownProperty: function(key) {
if (this.get('_allFields').contains(key) && this.get('_buffers').get(key)) {
return this.get('_buffers').get(key);
} else {
return this._super(key);
}
},
_save: function() {
var _this = this;
var object = this.get('content')
if (!this.get('content.isSaving')) {
console.log( "App.AutosavableController::_save: Saving Changes...");
//Start pacifier
NProgress.set(0).start()
//any buffered changes we have made get rolled into this save
this.get('_buffers').forEach(function(key, value) {
return _this.get('content').set(key, value);
});
//now clear out our buffer.
this.set('_buffers', Ember.Map.create());
// Callback method and Observers to stop pacifier
var progressDone = function(object){
NProgress.done()
}
object.on("didCreate", progressDone)
object.on("didUpdate", progressDone)
return object.save();
} else {
return this._debouncedSave();
}
},
_debouncedSave: function(immediate){
console.log("App.AutosavableController::_debouncedSave: Save requestsed and scheduled: ", AUTOSAVE_DELAY)
Ember.run.debounce(this, this._save, AUTOSAVE_DELAY, immediate)
},
// When the model is about to change out from under the controller we must
// immediately save any pending changes and clear out the _buffers.
_saveNowAndClear: function() {
console.log("App.AutosavableController::_saveNowAndClear: clearing...")
if (!this.get('content') || this.get('content.isDeleted')) {
return;
}
// FOR NOW, call immediate save because there is some bug in the immediate argument of Ember.run.debounce
this._save();
// TODO, use this once it works right...
// this._debouncedSave(true);
return this.set('_buffers', Ember.Map.create());
}.observesBefore('content'),
// ACTIONS kick off decorated methods from our views
actions: {
save: function(){
// FOR NOW, call immediate save because there is some bug in the immediate argument of Ember.run.debounce
this._save();
// TODO, use this once it works right...
// this._debouncedSave(true);
},
},
});
@Genkilabs
Copy link
Author

Usage, add the mixin to the model and controller and include the names of the fields you want saved in the controller:
App.DocumentController = Ember.ObjectController.extend App.AutoSaving,
bufferedFields: ['title', 'body']
instaSaveFields: ['postedAt', 'category']

@seifsallam
Copy link

@Genkilabs Any tips on how I can get bufferedFields to observe relation fields too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment