Ian
Ian

Reputation: 4185

Editing a record in Ember without updating the UI

I'm using Ember and Ember-Data and I'm trying to edit a record. The problem is that since inputs are two-way-bound to the model, modifying something in the form immediately changes the model throughout the application (even though I don't commit the changes). Hence, the changes reflect everywhere in the site even though they aren't stored.

What is the Ember way of editing records without modifying them until the user actually confirms the changes? Is there a way to clone models?

Upvotes: 1

Views: 247

Answers (1)

Josh Padnick
Josh Padnick

Reputation: 3268

That's really funny, I just myself ran into this, came up with a solution, and documented it in my own Stack Overflow question at Calling myModel.save() Returning Outdated Model. Scroll down to the SOLUTION part, second bullet.

My perception is that this pattern, while very common, is still not well-documented in the Ember community. For example, see these recent discussions:

I solved this by doing the following:

  • Hook into the willTransition event in your route so that, whenever your page that is doing the editing is transitioned out of, you can execute code right before that happens. Note that this covers both clicking your way out, or back-button'ing out. If the user closes their browser, these changes are lost anyway, so nothing extra needed to handle that situation.
  • Now in that hook, get your model with this.controller.get('model') and look at the value of isDirty with this.controller.get('model').get('isDirty'). See http://emberjs.com/guides/models/working-with-records/ for discussion on how to understand isDirty.
  • If isDirty is true, then call rollback() on your model as documented at http://emberjs.com/api/data/classes/DS.Model.html#method_rollback.
  • This will revert any unsaved changes so that the rest of your app looks consistent.

I have a model orgUser which has a belongsTo relationship to a model orgPerson. This relationship is set to { async: true }. Rolling back the orgPerson relationship worked like this for me:

Ember.Route.extend({
    actions: {
        willTransition: function( transition ) {
        this.controller.get('model.orgPerson').then( function( value ) {
            if ( value.get('isDirty') ) {
                value.rollback();
                }
            });
        },
    }
}

Note that you (a) may not need to wrap your isDirty call in a promise like I did (e.g. if you don't declare { async: true }, and (b) you may just access value.get('model') if you don't have a relationship to deal with.

Note also that, in my experience, myModel.rollback() does not rollback any of the relationships! That may only be because I'm using { async: true } for every relationship, but this is definitely something to watch out for.

Special thanks to @kingpin2k for pointing me in the right direction on my original SO post.

Upvotes: 3

Related Questions