I have been working with “Ember and Ember Data”:http://emberjs.com/ for the past few projects. We’ve recently had cases where we have a dirty form state (unsaved changes) and we want to restrict actions to prevent data loss.
We’ve come up with a solution that lets us get a rough track on the current state of Ember Data objects without implementing state tracking in every Ember controller. But we warned, it’s not entirely fool-proof, there are some manual parts to the process, and it may require a little fixing to fit your needs.
Ember Store Improvements
DS.Store.reopen recordsToReset:  dataWasUpdated: (type, record) -> recordsToReset = @get('recordsToReset') return unless $.inArray(record, recordsToReset) == -1 if record.get('isDirty') changes = record.changedAttributes() changedKeys = Ember.keys(changes) if record.get('dirtyType') == "created" validChanges = false record.eachAttribute (attr, meta) -> if attr in changedKeys hasChanges = false if meta.options and meta.options.defaultValue hasChanges = true unless changes[attr] == meta.options.defaultValue else hasChanges = true if hasChanges validChanges = true unless Ember.isBlank(changes[attr]) and Ember.isBlank(changes[attr]) return unless validChanges recordsToReset.pushObject(record) resetDirtyRecords: -> @get('recordsToReset').forEach (record) -> while record.get('isDirty') record.rollback() @set('recordsToReset', ) hasDirtyRecords: -> for dirty in @get('recordsToReset') changes = dirty.changedAttributes() !!@get('recordsToReset').findBy('isDirty', true)
The code above works well for Ember 1.5 and Ember Data 1.0 Beta 7. You can manually call
@store.resetDirtyRecords() to clean up at any point. This would generally follow a call to
@store.hasDirtyRecords() to check if there are dirty records then prompting the user if they want to cancel edits, if there are any. When the user agrees to cancel edits, you can then use
@store.resetDirtyRecords() to clear the changes.
Careful! This will clear all changes tracked. If you only want to cancel changes on a certain model, you should call
.rollback() on that individual model. Also, the logic behind the what makes a “dirty record” is as follows:
# A new record has values that are not default. (If you didn’t specify a default, then default is undefined.)
# The change to a blank value must not change to another blank value. (Undefined to blank string changes do not dirty the record.)
# Relationship changes can dirty a record. (Adding a child to a has many will unintentionally dirty a record.)