|
Ember.EditController = Ember.Mixin.create( |
|
saveError: false |
|
saveInvalid: false |
|
isEditing: false |
|
|
|
# Set associations to be associations of the content. These will then be checked for validity on save |
|
# and all of the flags, such as isDirty and isLoaded, will take these associations into consideration. |
|
# |
|
# Eg: A user may have an address model which is edited within the same transaction. |
|
# In this case you would put: |
|
# associations: ['address'] |
|
# |
|
associations: [] |
|
|
|
# Build an array of models that we will check for things such as isSaving, isLoaded, isDirty etc... |
|
models: (-> |
|
$.map($.merge(['content'], @get('associations')), (value, i) => |
|
@get(value) |
|
) |
|
).property('content', 'associations') |
|
|
|
# This will be called from the edit action, or can be called from a setupController on a route. |
|
startEdit: -> |
|
unless @get('isEditing') |
|
@set('isEditing', true) |
|
|
|
# This action exists to be called from an edit view |
|
edit: -> |
|
@startEdit() |
|
this.send('editing', @get('content')) |
|
|
|
cleanup: -> |
|
@set('isEditing', false) |
|
@set('saveError', false) |
|
@set('saveInvalid', false) |
|
@set('errors', null) |
|
if @get('isDirty') and !@get('isDeleted') |
|
@get('transaction').rollback() |
|
|
|
cancel: -> |
|
@cleanup() |
|
# Send action to the router |
|
@send("cancelled", @get('content')) |
|
|
|
resetTransaction: -> |
|
@get('models').forEach((model) => |
|
if model.get('isError') or not model.get('isValid') |
|
if model.get('id') |
|
# Horrible force the model state back to loaded.updated so it looks like an object loaded from the server |
|
# ready to be committed. |
|
model.get('stateManager').transitionTo('loaded.updated.uncommitted') |
|
else |
|
# Horrible force the model state back to created so it looks like an new object ready |
|
# to be committed again. |
|
# For some reason, model.isDirty is false now and I don't know how to get it to be dirty again. |
|
model.get('stateManager').transitionTo('loaded.created.uncommitted') |
|
) |
|
|
|
save: -> |
|
# Check before save |
|
if typeof @beforeSave == 'function' |
|
return unless @beforeSave() |
|
|
|
# Remove the errors |
|
@set('errors', []) |
|
@set('saveError', false) |
|
@set('saveInvalid', false) |
|
|
|
# Observe the record until it is finished saving |
|
@addObserver('isSaving', this, -> |
|
return if @get('isSaving') |
|
@set('saveError', @get('isError')) |
|
unless @get('isError') or @get('isInvalid') |
|
# The content is valid, we can remove the observer |
|
@removeObserver('isSaving') |
|
# If this is a new record, we want to wait until the id is populated before firing the saved event |
|
unless @get('content.id') |
|
@addObserver('content.id', this, -> |
|
# We have an id, remove the observer and fire the event |
|
@removeObserver('content.id') |
|
@set('isEditing', false) |
|
@send("saved", @get('content')) |
|
) |
|
else |
|
# This is an existing record, we can fire the saved event |
|
@set('isEditing', false) |
|
@send("saved", @get('content')) |
|
else |
|
# The record is either in error or invalid, we will reset the transaction. |
|
@removeObserver('isSaving') |
|
@resetTransaction() |
|
) |
|
# Now lets try to save |
|
@get('transaction').commit() |
|
|
|
isSaving: (-> |
|
@get('models').filterProperty('isSaving', true).get('length') > 0 |
|
).property('[email protected]') |
|
|
|
isDirty: (-> |
|
@get('models').filterProperty('isDirty', true).get('length') > 0 |
|
).property('[email protected]') |
|
|
|
isLoaded: (-> |
|
@get('models').filterProperty('isLoaded', false).get('length') == 0 |
|
).property('[email protected]') |
|
|
|
isError: (-> |
|
return false if @get('saveError') |
|
@get('models').filterProperty('isError', true).get('length') > 0 |
|
).property('[email protected]') |
|
|
|
isValid: (-> |
|
# Because we are forcing the model to become unsaved again, it clears the isValid flag. However certain |
|
# things (namely ember-bootstrap) rely on this flag to show validation errors, so if we have had an invalid |
|
# save we return false. |
|
return false if @get('saveInvalid') |
|
@get('models').filterProperty('isValid', false).get('length') == 0 |
|
).property('[email protected]') |
|
|
|
isInvalid: (-> |
|
!@get('isValid') |
|
).property('isValid') |
|
) |
|
|
|
Ember.DestroyController = Ember.Mixin.create( |
|
delete: -> |
|
@addObserver('content.isDeleted', this, -> |
|
if @get('content.isDeleted') |
|
@removeObserver('content.isDeleted') |
|
@send("deleted", @get('content')) |
|
) |
|
@get('content').deleteRecord() |
|
@get('transaction').commit() |
|
) |
Hi Bourke,
Yes I'm not sure what I was thinking when I wrote that route. It caused some trouble like that. Realistically, I think case specific what you do here. The cancel event should be called when a user has verified that they wish to cancel. I think you should implement your own deactivate to handle this situation. I've updated the gist to do the absolute basics without using the cancel action at all.