How can you prevent cursor item helpers from being rerun when the limit changes?

160 views Asked by At

Here is a modified leaderboard:

http://meteorpad.com/pad/CgEG3uYBZDceTERXA/Leaderboard

I added a limit to the players cursor and display scorePlusOne instead of score.

Template.leaderboard.helpers({
  players: function () {
    return Players.find({}, { sort: { score: -1, name: 1 } , limit: Session.get('limit')});

Template.player.helpers({
  scorePlusOne: function() {
    console.log('scorePlusOne',this.name);
    return this.score + 1;

When I increase the limit from 1 to 2, the first player template is not rerendered, but the scorePlusOne helper is rerun.

enter image description here

I don't want any helpers of already-rendered templates to rerun unless they contain reactive data that changes. Is there any way to achieve this behavior?

2

There are 2 answers

0
Loren On BEST ANSWER

Cache template helper results in ReactiveVars and move the helper code to template autoruns:

https://github.com/meteor/meteor/issues/4960#issuecomment-132715347

3
Billybobbonnet On

I don't think you can avoid helpers to be run when reactive data is updated.

However, one way to overrun this could be to use the tracker.autorun() function to wrap a flag to true and allowing your helpers to run or not. It will switch to true as soon your template is re-rendered because of a reactive element.

It would look like this:

Template.leaderboard.rendered = function() {
  this.autorun(function(){ 
     flag = true 
  });
};

And your helper would look like this:

Template.leaderboard.helpers({
  players: function () {
    if (flag===true){
     return Players.find({}, { sort: { score: -1, name: 1 } , limit:            
     Session.get('limit')});
    }
  },
  selectedName: function () {
   if (flag===true){
    var player = Players.findOne(Session.get("selectedPlayer"));
    return player && player.name;
    }
  }
});

Each time you make your change, just set your flag = false and that should do the trick.