Ember js @each one level deep but I have a two deep level relationship [duplicate]

↘锁芯ラ 提交于 2019-12-05 18:20:42

Why does this problem exist

Ember API indeed allows you to use only one level of @each/[] in your computed property dependencies.

This limitation is likely artificial as using two or more @each levels is a huge performance impact on internal observer maintenance.

Thus, you have to avoid more than one @each/[] in your CP dependency chains.

If you can't have a cake with N candles, have N cakes with one candle each

But sometimes your business dictates you to have to or more levels.

Fear not! This can be achieved with a chain of computed properties, where each property has only one @each level.

Say, you have Foo, Bar and Baz models and want to depend on

foos.@each.bars.@each.bazes.@each.name

Here's a chain of computed properties you need to create:

  • barsArrays: computed('foos.@each.bars') -- map foos by bars. You'll have an array of arrays of bars.
  • bars: computed('barsArrays.[]') -- flatten it to receive an array of bars.
  • bazesArrays: computed('bars.@each.bazes') -- map bars by bazes.
  • bazes: computed('bazesArrays.[]') -- flatten bazesArrays.
  • bazesNames: computed('bazes.@each.name') -- map bazes by name.

How to make the chain shorter

Note that you can make this chain shorter (but not necessarily more performant) by relying on the fact that bar.bazes is a relationship array that is never replaced with a different array (only its content changes, but the array object stays the same).

  • bazesArrays: computed('foos.@each.bars')-- map foos by bars, flatten, then map by bazes. You'll have an array of arrays of bazes.
  • bazes: computed('bazesArrays.[]') -- flatten bazesArrays.
  • bazesNames: computed('bazes.@each.name') -- map bazes by name.

Here's a working demo: http://emberjs.jsbin.com/velayu/4/edit?html,js,output

model.forEach(function(item) {
  item.set('sale_price', item.get('dealers_sched_id.sale_price'));
});

in this line here, you are essentially trying to create an alias, which is the right idea, becuase it is a "model-level" concern.. which you are tying to do at the controller level.

You could create a computed.alias('dealers_sched_id.sale_price') on your model definition, and avoid all the extra layers of computing properties.

Edit: in your case we are dealing with an asynchronous relationship

This means you need to be aware that the value will not always be available to you when the relationship promise is still resolving itself. the reason you are getting a NaN is that the belongsTo is still technically "loading"... so any synchronous function you try to perform is likely to fail on you.

When you look at both answers provided to you, involving computed properties, understand that both approaches will work... they will compute and recompute when the promises resolve.

somewhere in your code, you might be trying to access the eventual value, before it is actually ready for you... maybe an alert() console.log() or one of Ember's synchronous life-cycle hooks (hint: the setupController)?

Another approach, could be to use your route's model() hook or afterModel() to ask for the dealers_sched_id object before resolving the route... it may be less ideal, but it will ensure you have all the data you need before trying to use the values.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!