Search code examples
javascriptmongodbmeteoriron-router

Meteor template not reactive after using back button or Iron routing


I have a simple template that shows a list of websites and a details page that allows users to post comments about the site. For some reason, when clicking the back button in the browser or Iron router link to another page then going back again the update function for the comments is no longer reactive. The collection is updated but not rendered to the template. No errors are thrown in the console.

I suspect an issue with my helpers but I'm a complete noob and have struggle for 7 or more days to understand meteor, mongo, react....after taking a short course on it....

My code to update the collection:

Template.website_details_form.events({
    "submit .js-add-comment": function(event) {
        var post, theID;
        post = event.target.post.value;
        theID = this._id;
        console.log("the post:" +post);  
        console.log("this is the id: " +theID);

        if(Meteor.user()) {     
             var user = Meteor.user().username;
             if (post != ""){
                 Websites.update({_id: theID}, {$addToSet:{comments:{user:user, comment:post}}});
                 $('input#post').removeClass('error');
             } else{
                 $('input#post').addClass('error');   
             }
         } else {
             swal("Please sign in to post!", "Oops...", "error");
         }      
         event.preventDefault();
     }
});

My helpers admittedly funky helpers:

var details_ID;
var thecomments; 
Template.website_details.helpers({
    sites:function() {      
        if(details_ID === undefined) {
            return Websites.find(
                { title: 'Goldsmiths Computing Department' });
        } else {            
           return Websites.find({_id:details_ID});
        }                
     }
}); 

Template.website_details_item.helpers({
    comments:function() {
        if(thecomments === undefined) {
            var c = Websites.find({title: 'Goldsmiths Computing Department'}).fetch();
            return c[0].comments;
         } else {
            return thecomments;
         }
     }
});

Template.website_details_form.helpers({
    identify:function(){
    if(details_ID === undefined){
        return Websites.find({ 
            title: 'Goldsmiths Computing Department' });
        } else {            
            return Websites.find({_id:details_ID});
        }            
     }
});

my router:

Router.route('/website_details', function () {
    this.render('navBar', {to: 'navbar' });    
    this.render('website_details', {to: 'main'});
});

I'm using a click function on a document to get the information for my vars that I used in the helpers....this._id,

I did see another question that specifically asked about reactivity after using the back button and iron routing, but that thread terminated at a github page with little interaction and addressed a issue I don't have...to my knowledge...I am a noob...Thanks in advance.


Solution

  • Looking at the code, I found that:

    1. In the Template.website_details_form.events, the Websites collection is getting updated correctly.
    Websites.update({ // Saving to collection
       _id : theID
    }, {
       $addToSet : {
          comments : {
             user : user, 
             comment : post
          }
       }
    });
    
    1. However, in the Template.website_details_item.helpers, the comments data is being read from Session and not the Websites collection.
    ...
    comments: function(){ 
       var post = Session.get('site'); // Reading from Session
       return post.comments;
    },
    ...
    

    Two suggestions to fix this problem:

    1. When accessing the data from helpers, read it directly from the Websites collection:
    var site_data = Websites.findOne({
       _id: someId
    });
    
    if(site_data) { // Check if comments_data is undefined
       return site_data.comment;
    } else {
       return null;
    }
    
    1. When updating Websites collection, immediately update Session data:
    Websites.update({ // Saving to collection
       _id : theID
    }, {
       $addToSet : {
          comments : {
             user : user, 
             comment : post
          }
       }
    }, function(err, data) {
          if(!err) {
             var site_data = Session.get('site');
             /* Modify site_data */
             Session.set('site', site_data);
          }
    });
    

    I would suggest the first option, as it avoids storing large amounts of data in the Session and because the client-side minimongo collection is already storing the same data.