2
votes

So, I'm having a problem with a template helper I'm trying to use.

I'm using the helper to return a class, depending on a database entry. It does work correctly when the template is loaded, but it seems that the helper is not rerun when the database entries change (eg. the button is clicked and the event calls the update method).

I would like the helper to rerun when the click event calls the update method.

Any ideas?

Template:

<template name="modalPost">
  <div id="modalPost" class="modal fade" role="dialog" aria-labelledby="gridSystemModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
      <div class="modal-content">

        [...]

    <div class="modal-body">
      <div class="row">
        <div class="col-sm-5">
          <div class="col-xs-12">
            <a href="#" class="upvote btn btn-default {{upvotedClass}}">⬆</a>
            <a href="#" class="downvote btn btn-default {{downvotedClass}}">⇩</a>
          </div>
        </div>
      </div>
    </div>

        [...]

    </div><!-- modal-content -->
  </div><!-- modal-dialog -->
</div><!-- id: bugModal -->

Helper:

Template.modalPost.helpers({

 'upvotedClass': function() {
   var userId = Meteor.userId();
   if (userId && !_.include(this.upvoters, userId)) {
     return 'upvotable';
   } else if (userId && _.include(this.upvoters, userId)) {
     return 'btn-success disabled';
   } else {
     return 'disabled';
   }
 },

 'downvotedClass': function() {
   var userId = Meteor.userId();
   if (userId && !_.include(this.downvoters, userId)) {
     return 'downvotable';
   } else if (userId && _.include(this.downvoters, userId))  {
     return 'btn-danger disabled';
   } else {
     return 'disabled';
   }
 }

});

Events:

Template.modalPost.events({

 'click .upvotable': function(e, template) {
   e.preventDefault();
   Meteor.call('upvotePost', this._id);
 },

 'click .downvotable': function(e) {
   e.preventDefault();
   Meteor.call('downvotePost', this._id);
 }

});

// probably not relevant for question, but for convenience :-)

Methods:

Meteor.methods({
 'upvotePost': function(post_id){
   var post = Posts.findOne(post_id);
   if (!post) {
     console.log('error, post not found');
   } else if (_.include(post.upvoters, this.userId)) {  // if already upvoted
     console.log('error, already upvoted this post');
   } else if (_.include(post.downvoters, this.userId)) {  // if downvoted before
     Posts.update(post._id, {
       $addToSet: {upvoters: this.userId},
       $pull: {downvoters: this.userId},
       $inc: {votes: 2}
     });
   } else {         // if vote for first time
     Posts.update(post._id, {
       $addToSet: {upvoters: this.userId},
       $pull: {downvoters: this.userId},
       $inc: {votes: 1}
     });
   }
 },

 'downvotePost': function(post_id){
   var post = Posts.findOne(post_id);
   if (!post) {
     console.log('error, post not found');
   } else if (_.include(post.downvoters, this.userId)) { // if already downvoted
     console.log('error, already downvoted this post');
   } else if (_.include(post.upvoters, this.userId)) { // if upvoted before
     Posts.update(post._id, {
       $addToSet: {downvoters: this.userId},
       $pull: {upvoters: this.userId},
       $inc: {votes: -2}
     });
   } else {         // if vote for first time
     Posts.update(post._id, {
       $addToSet: {downvoters: this.userId},
       $inc: {votes: -1}
     });
   }
 }
});
1

1 Answers

0
votes

I think that your reactive data source in helpers is always the same. That is why it will not rerun. Your reactive data source is Meteor.userId() here. You need other query which will return different results over time. Or you can use Session or ReactiveVar.

Here you can try to use reactive Template.currentData() maybe it helps. But I have not tested it. So in helpers for example:

'upvotedClass': function() {
    var currData = Template.currentData();
    var userId = Meteor.userId();
    if (userId && !_.include(currData.upvoters, userId)) {
        return 'upvotable';
    } else if (userId && _.include(currData.upvoters, userId)) {
        return 'btn-success disabled';
    } else {
        return 'disabled';
    }
}