How can I work with related models in a computed property in a controller?


#1

I have a route that loads all order-items. Each order-item has one product. In the controller, I want to compute the total of the order by going through all the order-items and multiplying order-item.quantity by order.product.price. However, order.get(‘product.price’) does not return the price. I think this is because the relationship is asynchronous. The result of the total computed property is NaN. How do I fix this? Thank you!

I also created a JSBin http://emberjs.jsbin.com/lisedavela/edit?html,js,output

And here is the relevant code:

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return this.store.find('order-item');
  }
});

App.IndexController = Ember.Controller.extend({
  total: function() {
    return this.get('model').reduce(function(total, order) {
      return total + order.get('product.price');
    }, 0);
  }.property('model.@each.quantity')
});

App.OrderItem = DS.Model.extend({
  quantity: DS.attr('number'),
  product: DS.belongsTo('product', { async: true })
});

App.Product = DS.Model.extend({
  title: DS.attr('string'),
  price: DS.attr('number')
});

App.Product.reopenClass({
  FIXTURES: [
    { id: 100, title: 'Product A', price: 10 },
    { id: 200, title: 'Product B', price: 20 },
    { id: 300, title: 'Product C', price: 30 }
  ]
});

App.OrderItem.reopenClass({
  FIXTURES: [
    { id: 1, quantity: 5, product: 100 },
    { id: 2, quantity: 2, product: 200 },
    { id: 3, quantity: 1, product: 300 }
  ]
});

#2

Quick example, http://emberjs.jsbin.com/qobahe/edit?html,js,output

You’re seeing NaN because you’re doing (0 + PromiseObjectInstance). I probably wouldn’t use an observer for this, but threw it in there as an example. Observers setting props quickly becomes difficult to debug. It is probably more appropriate to move to an action if quantity was mutable from the UI.


#3

Thanks Jason! Wow, that definitely wasn’t as easy as I thought it would be. Even if I have an action to handle changing the quantity, I’d still have to run the same set of code to compute the total. How would an action make this computation simpler?

Is there a better way to set up my models so that this simple computation is easier?


#4

Even if I have an action to handle changing the quantity, I’d still have to run the same set of code to compute the total.

Correct.

How would an action make this computation simpler?

It’s to align closer to actions up, data down. Observers in general make your app increasingly and usually needlessly complex to understand the flows. That was the point I was making.