Javascript 绑定到Ember.js中的嵌套模型

Javascript 绑定到Ember.js中的嵌套模型,javascript,ember.js,Javascript,Ember.js,我有以下型号: App.Checklist = DS.Model.extend({ name: DS.attr('string'), checkitems: DS.hasMany('App.Checkitem', { embedded: true }), remainingItemsCount: function() { var checkitemsToCount = this.get('checkitems'); return checkitemsToCount.

我有以下型号:

App.Checklist = DS.Model.extend({
  name: DS.attr('string'),
  checkitems: DS.hasMany('App.Checkitem', { embedded: true }),

  remainingItemsCount: function() {
    var checkitemsToCount = this.get('checkitems');
    return checkitemsToCount.filterProperty('isDone', false).get('length');
  }.property()

});
我想显示一个检查列表列表,每个列表都有当前打开的检查项的计数

如果将以下内容放入模板中,则会得到正确的输出:

{{#each checklists}}
  {{this.name}}
  {{this.remainingItemsCount}}
{{/each}}
但是,如果将新的检查项目添加到检查表中,则计数不会增加

但是,如果我更改检查表模型中的
remainingitemsunt
computed属性,使其依赖于
checkitems.@each.done
,则计数会随着新检查项的添加而增加

问题是,一旦添加了此依赖项,子checkitems的集合就错了-它会不断重复第一个checkitem以获得总checkitems数(即,如果有五个项目的'isDone'为假,四个项目的'isDone'为真,则列表计数将显示为9,并且第一个检查项目将重复9次)

我做错了什么

更新:

事实证明,将依赖项添加到remainingitemsbunt属性会导致ember数据对服务器进行新调用

如果没有依赖项,则在页面加载时会发出以下XHR请求:

GET http://localhost:3000/checklists
GET http://localhost:3000/checklists
GET http://localhost:3000/checkitems
对于依赖项,页面加载时会发出以下XHR请求:

GET http://localhost:3000/checklists
GET http://localhost:3000/checklists
GET http://localhost:3000/checkitems
最后一个请求带有以下参数,这些参数似乎是第一个checkitem的表示形式,包装在“ids”散列中:


我想知道这是否是因为
checkitem
模型是用belongsTo属性定义的

App.Checkitem = DS.Model.extend({
  title: DS.attr('string'),
  isDone: DS.attr('boolean'),
  checklist: DS.belongsTo('App.Checklist')
});
更新2

我仍然不确定为什么,但很明显,向属性添加依赖项如下

remainingItemsCount: function() {
    var checkitemsToCount = this.get('checkitems');
    return checkitemsToCount.filterProperty('isDone', false).length;
}.property('checkitems.@each.isDone').cacheable()
…导致ember data的内置DS.RESTAdapter调用findMany。findMany请求应采用一个ID数组,但将向其传递一个数组,该数组包含嵌套在散列中的一个完整checkitem对象,该散列的键为0

解决方案

最后,我将问题追溯到了ember数据中的以下观察者:

dataDidChange: Ember.observer(function() {
    var associations = get(this.constructor, 'associationsByName'),
        data = get(this, 'data'), store = get(this, 'store'),
        idToClientId = store.idToClientId,
        cachedValue;

    associations.forEach(function(name, association) {
      if (association.kind === 'hasMany') {
        cachedValue = this.cacheFor(name);

        if (cachedValue) {
          var ids = data.get(name) || [];
          var clientIds = Ember.ArrayUtils.map(ids, function(id) {
            return store.clientIdForId(association.type, id);
          });

          set(cachedValue, 'content', Ember.A(clientIds));
          cachedValue.fetch();
        }
      }
    }, this);
  }, 'data')

当观测者到达行
return store.clientdforid(association.type,id)
时,数组
ids
是checkitem对象的数组,而不是id整数的数组。解决方法非常简单:
return store.clientdforid(association.type,id.id)
返回一个id整数数组。

我根据您的描述创建了一个JSFIDLE,无法重现您的问题。我使用的是Ember.js 0.9.6和Ember数据的最新版本,请参阅

把手


{{{#每个检查表}
{{this.name}}
剩余:{this.remainingitemsunt}
{{#每个检查项}
{{view Ember.Checkbox valueBinding=“isDone”}
{{/每个}}
添加项

{{/每个}} ​
JavaScript

App=Ember.Application.create({});
App.Checkitem=DS.Model.extend({
isDone:DS.attr('boolean')
});
App.Checklist=DS.Model.extend({
名称:DS.attr('string'),
checkitems:DS.hasMany('App.Checkitem'{
是的
}),
remainingItemScont:函数(){
var checkitemsToCount=this.get('checkitems');
返回checkitemsToCount.filterProperty('isDone',false).get('length');
}.property('checkitems@each.isDone').cacheable()
});
App.store=DS.store.create({
修订:4
});
App.checklistsController=Ember.ArrayProxy.create({
内容:App.store.find(App.Checklist)
});
Ember.View.create({
templateName:“检查表”,
checklistsBinding:'App.checklistsController',
addCheckitem:函数(evt){
var检查表=evt.context;
checklist.get('checkitems').addObject(App.Checkitem.createRecord({
isDone:错
}));
}
}).append();
var checklist=App.checklist.createRecord({
姓名:'firstChecklist'
});
App.Checklist.createRecord({
姓名:'secondChecklist'
});
checklist.get('checkitems').addObject(App.Checkitem.createRecord({
isDone:错
}));
checklist.get('checkitems').addObject(App.Checkitem.createRecord({
是的
}));
checklist.get('checkitems').addObject(App.Checkitem.createRecord({
是的
}));​

真的很有帮助!谢谢。事实证明,添加依赖项会导致余烬数据调用服务器的“/checkitems”url,其中一个哈希表示一个checkitems。我不知道为什么,但这几乎肯定是checkitems的ArrayProxy出现错误的原因。我想知道这是否是因为checkitem模型有一个
检查表:DS.belongsTo('App.checklist'))
属性。我不知道为什么会调用服务器。我从来没有为checkitem DS.Model设置url。但是您使用的是
DS.RESTAdapter
?因为这一个会自动计算您的url。也许这就是为什么您会接到服务器的调用。是的,这是使用内置的DS.RESTAdapter。我会仔细研究一下,看看是否可以跟踪问题是,也许我需要自己动手。