Search code examples
javascriptember.jsjsbin

Aggregation for Ember Data Async Relationships


I have an Invoice composed by more transactions, any transaction has a total amount as final result which comes from the multiplication of two values: quantity and fare

I am try to calculate the sum of all these total of any transaction

This is the error Uncaught TypeError: Cannot read property 'getEach' of undefined

I understand why this happens, the value total does not exist yet( because it s not still calculated)

This is my model with the function transactionsAmounts

App.Invoice = DS.Model.extend({
  title         : DS.attr('string'),
  transactions  : DS.hasMany('transaction', { async:true}),
  transactionsAmounts: function() {
    var sum = function(s1, s2) { return s1 + s2; };
    return this.get('model').getEach('total').reduce(sum);
  }.property('[email protected]'),
});

App.Transaction = DS.Model.extend({
  quantity: DS.attr('string'),
  fare: DS.attr('string'),
  total: DS.attr('string'),
  invoice: DS.belongsTo('invoice'),
  updateTotal: function() {

  // get the reference to the values of fare and quantity
  var quantity = this.get('quantity'),
      fare = this.get('fare');

  // massage them to make sure your stuff is not gonna break
  if (isNaN(fare)) { fare = 0; }
  if (isNaN(quantity)) { quantity = 0; }

  // calculate
  var total = fare * quantity;

  // set the total
  this.set('total', total);

}.observes('quantity', 'fare') 


});

this is an other function i have used to calculate all the totals and i get the same error

transactionsAmounts: function(){
    var totals = this.get("total");
    return totals.reduce(function(previousValue, total){
        return previousValue + totals.get("transactionsAmounts");
    }, 0);
}.property("[email protected]")

I have reproduced the case in this jsbin

How i can do it?


Solution

  • Here is a working js bin with your code bit modified : http://jsbin.com/lipakamasi/18/edit?js,console,output

    your problem is in your model declaration in which your are mixing few stuff :

    App.Invoice = DS.Model.extend({
    title           : DS.attr('string'),
    transactions  : DS.hasMany('transaction', { async:true}),
    transactionsAmounts: 0,
    setTransactionAmount : function(){
        if(this.get("transactions.length")>0){
          this.get("transactions").then(function(transactions){
          var sum=0;
          transactions.forEach(function(transaction){
            sum+=transaction.get("total");
           });
          this.set("transactionsAmounts",sum);
         }.bind(this));
       }
      }.observes('transactions.length', '[email protected]'), /
    });
    

    first of all look at the property or observes you try to refer to model.@each this is good for an ArrayController but you are in a DS.Model :) what you wanted to observes was the transactions.

    However those transactions are async thus ember will load a "promise" thus working with "async" javascript.