So I'm working on a forum type app. When the user navigates to a post, the url will be www.myapp.com/post/POSTID
. I'm using Iron Router to handle the routing.
Upon entering AND leaving this post, I want to update
a collection to indicate that the user has seen the post. I know that in Iron Router, if you modify one of the underlying subscriptions that the route is subscribed to, you run into an infinite reactivity loop. I was trying to update the collection in action()
before, but got an infinite loop.
So I moved the update
to onRun()
in the route. The infinite loop is gone, but the problem with onRun()
is that it won't trigger on hot reload. Every time I make a code change and Meteor hot reloads, the onRun()
code is not called. I have to manually do a ctrl-R
reload of my browser to get the onRun()
code to be actually called.
I wouldn't use the iron-router function to update this kind of value for several reason, starting with your objective:
I want to update a collection to indicate that the user has seen the post
If you want that, the least you can do is update once the template has been rendered. If you don't, a simple click on a link to your page aborted by another one will flag it as seen by the user.
Even better, you can watch the active
event and trigger a setInterval()
on this event. This way you can make sure that
It would look like this:
Template.yourTemplate.rendered = function() {
$(window).focus(function() { //for 3 seconds
Meteor.setInterval(function(){
//your update query
}, 3000);
});
The part where you intercept the user leaving the page is trickier. I just found a way to do it so I will share.
Make your subscription to your route controller (you do that already). This way, route loaded
= subscription active
and route left
= subscription stopped
Add an onStop()
function to the publication function and put inside it all the server side code you need to execute when the user leave the page. In your case, it would be an update related to the displayed post. Here is how my publication looks (I delete uploaded files when the related form hasn't been submitted when page is left), you should be able to adapt it to fit into your needs:
Meteor.publish("files", function(sessionId) {
var self = this;
// Here I clean all the files I need to remove because the user has
// not submitted the current form.
self.onStop(function () {
console.log (sessionId + " is cleaning...");
cleanFiles(sessionId)
});
// I look for files related to the current upload session only
if(Users.isInRoles(this.userId, ["user"])) {
return Files.find({"session_id":sessionId, "owner":this.userId}, {});
}
//and I make my publication available in case the if statement failed
return self.ready();
});
};