Possible to sort Collections by data that's calculated by a Template Helper?

Hi all,

I can’t for the life of me figure out how to sort a Collection by data that’s calculated via a template helper. Here’s what I’m working with:

// calc_pct_change_pretty is a Template helper 
{{# each destinations}}
...
{{ calc_pct_change_pretty currency.rates.daily.D0.rate currency.rates.yearly.Y1.rate }}
...
{{/each}}

A couple questions:

  1. Is it even possible to sort my collection by data that’s calculated via a template?
  2. Am I doing this all wrong – should I be doing all my calculations on the server? Or is there a better pattern for adding and manipulating (sorting / filtering / etc) data client-side that’s not necessarily stored permanently on the server?

I know there are plugins for this sort of thing. But, to the extent I can, I’d love to do it the “meteor way” and learn.

Thank you so much!

Not sure if it fits your use case, but you could check out creating a client-side only collection.

You could pull the relevant information from your server-side db, push it into a client-side collection, and then update those documents with all the calculations/extra data you have and still be able to query it like a normal collection. Though, you’d still have to think about reactivity, etc.

If you need to sort a fetched set by the computed value of 2 collection fields, you could use the underscore.js sortBy method on the client.
btw: I think the percentage change would be 20%.

@vigorwebsolutions - interesting. but doesn’t Meteor already do this for me by creating a minimongo Collection that mirrors the source Collection? Can I just manipulate this minimongo instance?

@rdagger - but I still need to display the computation, not just sort by it.

I’m still banging my head on the wall on this. Is there a rule of thumb for what computations should be done client-side vs. server-side?

Your options here seem to be:

  1. Store this data in the collection.
  2. Sort the data as presented (e.g. a jQuery plugin).
  3. Use a transform on the collection and return a sorted array in the helper.

Option 3 is probably the closest fit to what you seem to want to achieve in terms of functionality and doing it the Meteor way. Transforms are a really useful way of generating computed properties on a document. However, they do have a downside, in that they are only evaluated when the document is dereferenced from the cursor - so they’re not accessible in a find.

Given that you’re not presenting huge amounts of highly reactive data, you can still use this in a template helper by fetching the data and sorting before returning, so something like:

return MyCollection.find(...).fetch().sort((a,b) => {
  return a.thing === b.thing ? 0 : (a.thing < b.thing ? -1 : 1);
});

Where thing is a computed (transform) property.

I guess I consider trying to manipulate that minimongo without syncing the changes with the server-side collection a bit hacky. When it’s made sense for me in the past, I’ve created what the docs refer to as a local scratchpad that supports Mongo-style find, insert, update, and remove operations.

In your scenario, I’d pull the source data (country, todayRate, lastYearRate) into a client-only collection and then update those documents with your rateDifference and airfareFromSF. That way, you get all of the functionality of the cursor with data that isn’t persisted to your server-side collection.

Your returned collection still has the necessary input values so your helper can generate the computed output.