model和setupController钩子与未定义的模型

时间:2013-03-19 19:15:44

标签: routes ember.js

我的路线中有setupControllermodel钩子。 model.find(param)持有对rails后端的ajax调用。

我的模型钩子会触发并调用后端。但是在后端回答并且成功回调实际上回到模型之前,setupController钩子会触发一个仍未定义的模型。

最终结果是,当模型本身通过绑定系统进行更新时,需要在setupController中进行的其他设置无效。我觉得我以某种方式设置了模型的内容错误,但无法弄明白。

如果我使用后退和前进按钮进行导航,则只会发生这种情况。如果我通过指定对象的#linkTo进入路线,一切都按预期工作。

我的代码如下,如果有人有一个很棒的想法。

App.ProjectsEditRoute = Ember.Route.extend({
  model: function(params) {
    return App.Project.find(params.project_id);
  },

  setupController: function(controller, model) {
    this.controllerFor('activedataset.index').set('content', App.ActiveDataSet.findAll(model.id));
  }
});

App.Project = Ember.Object.extend({
  id: '',
  name: ''
});

App.Project.reopenClass({
  findAll: function() {
    var result = Ember.ArrayProxy.create({content: []});
    var self = this;
    $.ajax({
      url: '/projects.json',
      type: 'GET',
      data: {'user_id': App.currentUser.id},
      success: function(data, textStatus, xhr) {
        result.set('content', data.projects);
      },
      error: function(xhr, textStatus, errorThrown) {
        alert('error');
      }
    });

    return result;
  },

  find: function(project_id) {
    var result = Ember.Object.create({content: null});
    var self = this;
    $.ajax({
      url: '/projects/' + project_id + '.json',
      type: 'GET',
      success: function(data, textStatus, xhr) {
        result.setProperties(data.project);
      },
      error: function(xhr, textStatus, errorThrown) {
        alert('not found');
      }
    });

    return result;
  }
});

在Mike提供的解决方案后编辑:

App.ProjectsEditRoute = Ember.Route.extend({
  model: function(params) {
    var record = App.Project.find(params.project_id);
    var promise = Ember.Deferred.create();
    record.addObserver('isLoaded', function() {
      promise.resolve(record);
    });

    return promise;
  },

  setupController: function(controller, model) {
    this.controllerFor('activedataset.index').set('content', App.ActiveDataSet.findAll(model.id));
  }
});

App.Project.reopenClass({
  find: function(project_id) {
    var result = Ember.Object.create({content: null, isLoaded: false});
    var self = this;
    $.ajax({
      url: '/projects/' + project_id + '.json',
      type: 'GET',
      success: function(data, textStatus, xhr) {
        result.setProperties(data.project);
        result.set('isLoaded', true);
      },
      error: function(xhr, textStatus, errorThrown) {
        alert('not found');
      }
    });

    return result;
  }
});

2 个答案:

答案 0 :(得分:4)

  

我觉得我在某种程度上错误地设置了模型的内容,但无法弄明白。

你所做的事情本身并没有错。如果你需要使用ember路由器来等待模型ajax完成,然后再转到setupController钩子你的模型的find()应该返回一个promise。如果路由的模型挂钩返回一个promise,则ember路由器将等待promise的解析,然后再继续。

默认情况下,当调用find({})时,ember-data的模型对象会返回一个promise。对于您的模型应该很容易做同样的事情,请参阅此Ember initializing route model with query以获取延迟模式的示例。

  

如果我使用后退和前进按钮进行导航,则只会发生这种情况。如果我通过带有指定对象的#linkTo进入路径,一切都按预期工作。

有道理。当您使用#linkTo时,数据已经加载。

答案 1 :(得分:0)

您可能应该使用this.store.find('project')而不是滚动自己的App.Project.find()

DS使用promises,因此调用代码将等待获取的对象。

在铁轨和灰烬协同工作方面有什么不足之处, 是你可能应该在rails控制器中使用ActiveModel :: Serializers,在ams中使用DS.Store适配器以获得最佳和预期的结果。

App.Store = DS.Store.extend({
    // Override the default adapter with the `DS.ActiveModelAdapter` which
    // is built to work nicely with the ActiveModel::Serializers gem.
    adapter: '_ams'
});

我的经验是,如果你开始回避Ember和/或DS,你就会陷入痛苦的世界。使用Ember的难点在于,你可以说,必须要理解它的每个方面都是有效的。