dpatte dpatte - 2 years ago 80
jQuery Question

In Meteor, how can I do a sum of some computed fields in a table?

I have completely rewritten this question, because I have made some headway, and I also needed to clarify it further.

In general - I'd like to calculate row and column totals for a table, without having to recalculate each cell value twice. Let me explain.

I have a collection and each doc contains 12 values. For each doc, I need to perform two slow expensive calculations on these 12 doc values producing two results and then display these two results in a table.
Then I also need the sum of the two computed results on each row, and a sum of all the computed results for each column.

The page would look like this:

resa resb row1sum
resa resb row2sum
(etc)
col1sum col2sum


And a portion of the template might look like this:

<table>
{{#each docs}}
<tr><td>{{resa}}</td> <td>{{resb}}</td> <td>{{rowsum}}</td></tr>
{{/each}}
<tr><td>{{colsum1}}</td> <td>{{colsum2}}</td>
</table>


For each row, I am now using a transform clause in my cursor helper to generate the results and rowsums.

docs: function() {

return myCollection.find({},{transform: function(doc) {
var resa = slowcalculation1(doc);
doc.resa = resa;
var resb = slowcalculation2(doc);
doc.resb = resb;
doc.rowsum = resa+resb;
return doc;
}
});

},


This works well to calculate the two results and rowsum for each doc and is reactive.

But I am now trying to find a way to efficiently calculate the column sums.

I could use the following

Tracker:autorun(function()
{
var col1tot=0;
var col2tot=0;
myCollection.find().forEach(function(doc) {
var resa = slowcalculation1(doc);
col1tot += resa;
var resb = slowcalculation2(doc);
col2tot += resb;
});
Session.set('col1',col1tot);
Session.set('col2',col2tot);
// then get these coltotals using helpers
});


But is there a better way? As it stands, to generate the page, I am calling slowcalculations() twice for each cell, and I like to only calculate each cell value once, since my calculations are, ahem, slow. :)

Can I instead, somehow, calculate the column sums, but within in my cursor helper?

Or is there some other way to reactively take the whole collection and reactively generate both the rowsums and colsums in a single pass?

Answer Source

So, I believe I have an answer. It seems to work, at least.

I have modified my template helper that is passed to the template and it now looks like this

docs: function() {

var col1sum=0;
var col2sum=0; 

return myCollection.find({},{transform: function(doc) {
  var resa = slowcalculation1(doc);
  doc.resa = resa;
  var resb = slowcalculation2(doc);
  doc.resb = resb;
  doc.rowsum = resa+resb; // the rowsum

  col1sum += resa;
  col2sum += resb;
  Session.set('col1sum',col1sum);
  Session.set('col2sum',col2sum);
  // then get these colsums into template using helpers

  return doc;
  }
});

},

This calcs the row sums, and the column sums, minimizing the number of times slowcalculations() are done.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download