Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor template reload infinity

I have a problem when running with Meteor.

I have a "question" page which I want to increase the count view whenever it is rendered.

So in my template function I write

Template.questionview.helpers({
    question : function() {
      if(Session.equals('main_template_name', 'question')) {
        console.log(Session.get('question_id'));
        Questions.update({
          _id: Session.get('question_id')
        }, {
           $inc: {
           views: 1
        }
     });
   }
});

Now here comes the problem, when I render the question view and update the question item, the view is refreshed again because it is a reflective page. And then it comes infinity loop.

Anyone has suggestions?

like image 864
user857188 Avatar asked Dec 08 '12 10:12

user857188


2 Answers

Typically, in situations like this, there is something broken about the model. In this case, I believe it's the "count view" idea. There are lots of ways to do this correctly. Incrementing it on render is not, since you're doing model work in UI code (broken conceptually and in implementation).

First, store the questions the user has visited somewhere. Why not a {questionsVisited:[]} property on the user?

Use a Meteor.call(...) method call to register a view instead:

Meteor.methods({
  viewQuestion: function(questionId) {
    // check if the user hasn't visited this question already
    var user = Meteor.users.findOne({_id:this.userId,questionsVisited:{$ne:questionId}});

    if (!user)
         return false;

    // otherwise, increment the question view count and add the question to the user's visited page
    Meteor.users.update({_id:this.userId},{$addToSet:{questionsVisited:questionId}});
    Questions.update({_id:questionId},{$inc:{views:1}});
    return true;
});

So how about incrementing the view on UI changes? Well, let's not do that specifically. Let's increment the view count only when the question changes.

Meteor.autorun(function () {
  var questionId = Session.get("question_id");
  Meteor.call('viewQuestion',questionId,function(e,r) {
    if (r)
      console.log("Question " + questionId + " logged an increment.");
    else 
      console.log("Question " + questionId + " has already been visited by user " + Meteor.userId();
  });
});

And get rid of all this question helper stuff...

This is even better than what you originally wanted. Now views aren't counted twice for the same user. If that is the desired behavior, remove the questionsVisited logic.

Only change the 'question_id' session variable when you actually change the logical question the user is working with.

like image 56
DoctorPangloss Avatar answered Oct 03 '22 04:10

DoctorPangloss


I solved this problem by using meteor-collection-hooks

First install it

>_ meteor add matb33:collection-hooks

Then in your model

Questions.after.findOne(function (userId, selector, options, doc){
    Questions.update({_id: doc._id},{$inc:{views:1}});
});

And KABOOM Thats it

like image 23
dyaa Avatar answered Oct 03 '22 04:10

dyaa