简体   繁体   中英

Ember.js—Why would this.get('model') return a controller?

Here's a jsfiddle demonstration: http://jsfiddle.net/YUHLA/5/

This is a problem I ran into while trying to figure out the right pattern for creation of a new record. I can't get the newly created record to save, and I've encountered some odd behavior on the way.

Open the console, and try adding a new post and saving it. Notice three odd occurrences:

  1. Calling get('model') on the controller is returning a controller on line 62.
  2. On line 65, it's demonstrated that no new models were saved to the fixtures.
  3. After creating another post from the post controller and saving it, both posts are saved (line 70).

Here's the javascript:

window.App = Ember.Application.create();

App.Store = DS.Store.extend({
  adapter: DS.FixtureAdapter
});

App.store = App.Store.create();

App.Post = DS.Model.extend({
  title: DS.attr('string'),
  body: DS.attr('string')
});

App.Post.FIXTURES = [
  {
    id: 1,
    title: 'title',
    body: 'body'
  }, {
    id: 2,
    title: 'title two',
    body: 'body two'
  }
];

App.NewPostFormView = Ember.View.extend({
  tagName: "form",
  templateName: "newPostForm",
  submit: function() {
    this.get('controller').save();
    return false;
  }
});

App.ApplicationController = Ember.ObjectController.extend({
  posts: (function() {
    return App.Post.find();
  }).property()
});

App.PostsController = Ember.ArrayController.extend({
  sortProperties: ['id'],
  sortAscending: false,
  itemController: 'post',
  newPost: function() {
    var post;
    return post = App.Post.createRecord({
      title: '',
      body: '',
      isEditing: true
    });
  }
});

App.PostController = Ember.ObjectController.extend({
  save: function() {
    var temp;
    console.log('Starting to save');
    console.log('this.get(\'model\') =', this.get('model'));
    transaction = App.store.transaction();
    this.set('isEditing', false);
    temp = this.get('model');
    temp.get('store').commit(); 
      Ember.run.next(function(){
          console.log('# fixtures:', App.Post.FIXTURES.length);
          App.Post.createRecord(
              {title: 'post four', body: 'four body'}
          ).get('store').commit()
          Ember.run.next(function(){
             console.log('# fixtures:', App.Post.FIXTURES.length);
          });
      });
  }
});

Does this have to do with the fact that I'm creating the model from the posts controller, then saving it in the post controller? If so, how can I get around this?

Thanks!

Does this have to do with the fact that I'm creating the model from the posts controller, then saving it in the post controller?

No.

  1. Calling get('model') on the controller is returning a controller on line 62.

Right. PostsController has specified itemController: 'post' , so when the posts template iterates over {{each post in controller}} the posts are being wrapped in a PostController . That's fine but not in combination with the {{render}} helper. When {{render}} is used within the each block to {{render post post}} , it renders the post template and wraps the specified value (the post variable) in a PostController. So you've got two post controllers wrapping a single post model. Kinda overkill.

  1. On line 65, it's demonstrated that no new models were saved to the fixtures.

So issue here is that you have two different stores. App.store() is a global variable that was created on line 14. And since it was the first one created, it is the default store . It is not related to the one used by your model.

In PostController.save(), this.get('model') is returning a controller. And a controller's store is the default store. This is usually the same as the model's store but not in this case. So when you call get('store').commit() that is on the default store, which has no models, so nothing happens. If you really had a model (by fixing issue #1) this would have been ok. Or if you'd not created App.store it would also have been ok, since in that case the default store would've been the same as your model's store.

Would recommend not creating App.store() yourself, doing this is just confusing and probably not what you want. In general it is best to let ember create things.

  1. After creating another post from the post controller and saving it, both posts are saved (line 70).

Right. Because commit() was called on App.store(), App.Post's store still had one uncommitted record. App.createRecord({}).get('store').commit() creates a second record in that store then commits both.

Updated fiddle here: http://jsfiddle.net/YUHLA/7/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM