我必须访问我控制器上两层深的属性,但[]
只能通过emberjs指南深入访问一级。
model(params) {
params.paramMapping = {
page: "page",
perPage: "per_page",
total_pages: "pages"
};
return this.findPaged('contractf', params);
},
setupController(controller, model) {
model.forEach(function(item) {
item.set('sale_price', item.get('dealers_sched_id.sale_price'));
});
controller.set('content', model);
},
上面,我的模型基本上是在contractf模型中以分页格式获取所有记录。然后我设置我的控制器并遍历所有这些模型,并绑定一个sale_price
属性进入它的关系,以获得正确的模型关系中的sale_price。
现在在我的模板中,我有这个:
new_suggested_price: Ember.computed('selectedItems', 'selectedItems.[].sale_price', function() {
var ret = 0;
this.get('selectedItems').filterBy('car_used', 'N').forEach(function(contract){
var salePrice = contract.get('sale_price');
if (salePrice) {
ret += (salePrice*100);
}
});
return ret/100; // We *100/100, so we avoid a floating point calc error.
}),
基本上只给我一个易于格式化的数字。正如您所看到的,它取决于selectedItems(基本上是模型,但是属性过滤)。所以我必须进入每个模型项并找到我设置的sale_price
I属性,如果它发生变化,这个计算属性将更新。阅读Ember的指南,我无法selectedItems.[].dealers_sched_id.sale_price
,因为它只有一层深。
我认为在setupController上设置一个属性可以解决这个问题,但它似乎并不是因为我仍然将NaN
作为sale_price
值。
现在,如果我将setTimeout函数设置为500毫秒,它会填充正常。如何在页面加载时定义它?
感谢您的帮助。
答案 0 :(得分:16)
Ember API确实允许您在计算的属性依赖项中仅使用一级@each
/ []
。
这种限制可能是假设的,因为使用两个或更多@each
级别会对内部观察者维护产生巨大的性能影响。
因此,您必须在CP依赖关系链中避免多个@each
/ []
。
但有时候你的生意会要求你达到或超过等级。
不要害怕!这可以通过一系列计算属性来实现,其中每个属性只有一个@each
级别。
说,你有Foo,Bar和Baz模型,并希望依赖
foos.@each.bars.@each.bazes.@each.name
以下是您需要创建的一系列计算属性:
barsArrays: computed('foos.@each.bars')
- foos
地图bars
。你将拥有一系列条形数组。bars: computed('barsArrays.[]')
- 展平它以接收一系列酒吧。bazesArrays: computed('bars.@each.bazes')
- bars
地图bazes
。bazes: computed('bazesArrays.[]')
- 展平bazesArrays
。bazesNames: computed('bazes.@each.name')
- bazes
地图name
。请注意,依赖于bar.bazes
是一个永远不会被其他数组替换的关系数组(只有其内容发生更改,但是数组)这一事实,您可以缩短此链(但不一定更高性能)对象保持不变)。
bazesArrays: computed('foos.@each.bars')
- 按foos
映射bars
,展平,然后按bazes
映射。你将拥有一系列bazes阵列。bazes: computed('bazesArrays.[]')
- 展平bazesArrays
。bazesNames: computed('bazes.@each.name')
- bazes
地图name
。这是一个有效的演示:http://emberjs.jsbin.com/velayu/4/edit?html,js,output
答案 1 :(得分:0)
model.forEach(function(item) {
item.set('sale_price', item.get('dealers_sched_id.sale_price'));
});
在这一行中,你基本上是在尝试创建一个别名,这是正确的想法,因为它是一个"模型级"关注..你在控制器层面要做的事情。
您可以在模型定义上创建computed.alias('dealers_sched_id.sale_price')
,并避免所有额外的计算属性层。
编辑:在您的情况下,我们正在处理异步关系
这意味着您需要注意,当关系承诺仍在解决时,您并不总是可以使用该值。你得到NaN
的原因是belongsTo在技术上仍然是#34; loading" ...所以你尝试执行的任何同步功能都可能会失败。
当您查看提供给您的两个答案(涉及计算属性)时,请理解两个方法将工作......他们将在承诺解决时计算并重新计算。
在您的代码中的某个位置,您可能正在尝试访问最终值,然后才真正为您准备好......可能是alert()
console.log()
或其中一个Ember的同步生命周期钩子(提示:setupController)?
另一种方法可能是在解决路线之前使用您的路线model()
挂钩或afterModel()
来询问dealers_sched_id
物品......可能不太理想,但它会确保您在尝试使用这些值之前获得所需的所有数据。