我有3种不同的夹具型号,如下所示。
var Room = DS.Model.extend({
title: DS.attr('string'),
categories: DS.hasMany('Category', { async: true }),
isSelected: DS.attr('boolean')
});
var Category = DS.Model.extend({
title: DS.attr('string'),
room: DS.belongsTo('Room', {async: true }),
materials: DS.hasMany('Material', { async: true }),
isSelected: DS.attr('boolean')
});
var Material = DS.Model.extend({
title: DS.attr('string'),
category: DS.belongsTo('Category', {async: true} ),
isSelected: DS.attr('boolean')
});
我发现当我尝试查看Materials模型中的内容时,它是空白的。在我的控制器中,我通过这样做来公开材料:
currentMaterials: function() {
var room = this.filterBy('isSelected', true).get('firstObject');
var categories = room.get('categories');
var selectedCategory = categories.get('firstObject');
var material = selectedCategory.get('materials');
return material;
}.property('@each.isSelected')
但是,当我尝试访问currentMaterials时,该值为null。如果我首先使用{{#each}循环访问Rooms / Categories,我只能访问其值。奇怪的是,一旦我执行{{#each}},我就可以访问currentMaterials中的值。
有谁理解为什么?
答案 0 :(得分:1)
由于存在承诺的事实。您的categories
关系是异步的,这意味着它最初不存在,并且如果需要,ember-data应该获取它。但是,获取数据需要时间,因此ember-data会从此返回一个承诺:var categories = room.get('categories')
。在那个承诺之后,你首先从它获得firstObject
,这对于一个承诺是不存在的(为空),而不是从那个空得到materials
的关系。它只是空。
然而,ember模板是聪明的,如果你在它们上放each
,他们就知道需要这些关系,并使ember-data获取这些数据。
你能做什么?如果您需要此数据来执行特定于页面的作业,则应在向用户显示页面之前确保您可以访问它 - 因此在模型挂钩中。您可以使用Ember.RSVP进行多次提取调用并在控制器中进行设置:
model: function() {
data =
room: store.find("room")
categories: store.find("category)
materials: store.find("material")
return Ember.RSVP.hash(data)
}
但请注意,它会获取all
材料等。如果您只需要连接到模型的材料,则应考虑使用side loading加快数据提取速度。如果你正在使用灯具,它就不会工作。
最后我能想到的是使计算属性成为一个获取数据的方法,但是将它们设置在其他变量上。您可以使用某种标志在数据准备就绪时通知应用程序:
currentMaterials: function() {
var room = this.filterBy('isSelected', true).get('firstObject');
room.get('categories').then(function(categories) {
return categories.get('firstObject').get('materials');
}).then(function(materials) {
// here you have your materials
// you can pass _this to that method and set these materials
// on some kind of controller property (e.g. materialsChosen)
// and use a flag like setting 'is Fetching' on the start of this
// computed property and setting down right here
});
}.property('@each.isSelected')