createRecord on model leaves behind shell of a record when not saved. What are some solutions?


#1

Let’s say I have a concept for ‘user’ or an ‘order’ that uses a form. I can create a record on the store and return it in the model of a route. Then in the form, the data knows how to act based on that model schema. This is great (specifically - I’m using a mirage setup to experiment with some things).

When I visit the ‘orders/create’ route - or wherever the record is being created - it does just that - It creates the record / but then if I leave… the record is just kinda there for no reason. Is this a problem? How do people normally deal with this? If you aren’t listing the records, you might not even notice but if you look at the ember-inspector - you’ll see the records / or if you list them out in another route - you’d see a bunch of data-less list-items.

First thoughts would be to check when leaving the route - and delete the record / but that doesn’t seem very smooth. Then I could hold off on creating the record until I had all of the data / but then I couldn’t take advantage of computed properties. Or someone suggested I could just let them exist - and filter them out of lists by checking for something like the existence of an ID.

What do you think?

https://ember-twiddle.com/839c2597d32cfad801c87c358497ddd0?openFiles=routes.orders.js%2C


#2

It’s expected behavior for sure, it’s actually one of the really nice features of Ember, records with state. Basically when you do a createRecord it creates a new record that gets loaded into the store, but it has a state of “new” when it is in the “unsaved” state (aka it hasn’t been persisted to the backend yet).

If it’s not harming anything I’d say don’t worry about it. If it’s showing up somewhere you don’t want it to I’d say filter. The way we filter these in our app is by ‘isNew’. All records have a computed property called “isNew” which will return true if it is in that new/unsaved state. So you can do something like this in a controller/component:

notNewFruits: Ember.computed.filterBy('model.fruits', 'isNew', false), 

Another thing that we do in some of our routes/components (depending on how records are being created) is we load a “draft” record and then if the user switches views and switches back to the create view we load that same draft record back (which means they can partially edit the form, leave, then return and it’s all still there). This is an example of doing that in a route:

import Ember from 'ember';
import AuthenticatedRouteMixin from "../../mixins/authenticated-route-mixin";

export default Ember.Route.extend(AuthenticatedRouteMixin, {
  model: function(/*params ,transition*/){
    // if there's a record with 'isNew' set, it must have been a previous 'draft', so use
    // that, otherwise make a new 'draft' account record
    let newAccount = this.store.peekAll('account').findBy('isNew', true);
    newAccount = newAccount || this.store.createRecord('account', { /* default attrs */ });
    return Ember.RSVP.hash({
      account: newAccount,
    });
  },
});

#3

This is a great answer and explanation. Thank you.

Let me know if I can clarify the question + title / for future searches.


#4

I don’t think I can think of anything much clearer so I’d just leave it. Good luck!