Skip to content

Instantly share code, notes, and snippets.

@aboma
Created July 17, 2013 19:06
Show Gist options
  • Save aboma/6023481 to your computer and use it in GitHub Desktop.
Save aboma/6023481 to your computer and use it in GitHub Desktop.
Universal edit controller mixin for ember.js. Use on all controllers that create, update and delete records.
// Mixin to generalize model create/edit functionality
// for use in controllers. Typical use in route:
// Vilio.PortfolioEditRoute = Ember.Route.extend({
// // create transaction and add model to it
// setupController: function(controller, model) {
// this._super(controller, model);
// this.store.transaction().add(model);
// },
// events: {
// cancel: function() {
// this.controller.stopEditing();
// ...
// },
// save: function() {
// var route = this;
// this.controller.saveEdits().then(function() {
// console.log('saved');
// route.transitionTo...
// }, function() {
// console.log('error saving');
// });
// },
// remove : function(portfolio) {
// var route = this;
// this.controller.deleteRecord().then(function(){
// console.log('deleted');
// route.transitionTo...
// }, function() {
// console.log('error deleting');
// });
// }
// }
//});
Vilio.EditModelControllerMixin = Ember.Mixin.create({
needs:['message'],
// works for both save and edit by inspecting record states
// commit record if it has changed; returns promise of
// record create or update
saveEdits: function() {
var controller = this,
msgController = this.get('controllers.message'),
record = this.get('content');
return new Em.RSVP.Promise(function(resolve, reject) {
// reset transaction if user wants to resubmit record
// that is invalid or in error state
if (!record.get('isValid') || record.get('isError')) {
this.resetRecordState();
}
if (record.get('isDirty')) {
msgController.set('message', 'saving record');
var method = record.get('isNew') === true ? 'didCreate' : 'didUpdate';
// callback will show record once the id is available
record.one(method, controller, function() {
msgController.set('message', 'record saved');
if (method === 'didUpdate') {
// resolve promise
resolve(record);
} else {
// observe for when id is created since we may need this
// for transition
record.addObserver('id', this, resolve);
}
});
var errorHandler = function() {
var type = this.get('content.isError') ? 'error' : 'problem';
msgController.set('message', type + ' saving record');
this.get('content.transaction').rollback();
// reject promise
reject(record);
};
// callback for invalid or conflict response from server
record.one('becameInvalid', controller, errorHandler);
record.one('becameError', controller, errorHandler);
// trigger save
record.get('transaction').commit();
} else {
msgController.set('message', 'no changes to save in model');
resolve(record);
}
});
},
// returns promise to delete resource
deleteRecord: function() {
var controller = this,
msgController = this.get('controllers.message'),
record = this.get('content');
return new Em.RSVP.Promise(function(resolve, reject) {
msgController.set('message', 'deleting record');
record.one('didDelete', controller, function() {
msgController.set('message', 'record deleted');
resolve();
});
record.one('didError', controller, function() {
msgController.set('message', 'error deleting record');
reject(record);
});
record.deleteRecord();
controller.get('content.transaction').commit();
});
},
stopEditing: function(callback) {
var controller = this;
return new Em.RSVP.Promise(function(resolve, reject) {
controller.get('content.transaction').rollback();
resolve();
});
},
// enable transaction to be submitted again
resetRecordState: function() {
var record = this.get('content');
var state = record.get('id') ? 'loaded.updated.uncommitted' : 'loaded.created.uncommited';
record.get('stateManager').transitionTo(state);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment