IronRouter event function - meteor

Does iron router have an event when the Meteor app is loaded?
I would like to run a function when template 'loading' is display, and when app is loaded.

To display a template while loading put this line in the router file.
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading'
});
where loading is the loading template.
Alternatively: pcel:loading package from atmospherejs.

Router Hooks:
You can try to use the router hooks provided by iron-router such as waitOn, onBeforeAction etc. in conjunction with your loading template.
For example:
If you have a route named path and a subscription named foo being accessed on that route:
Router.route('/path', {
// this template will be rendered until the subscriptions are ready
loadingTemplate: 'loading',
waitOn: function () {
// perform action while database subscription loads
console.log('Fetching foo...');
return Meteor.subscribe('foo');
},
onBeforeAction() {
// perform action before route loads
console.log('Loading...');
this.next();
},
action: function () {
// perform action when route loads
// ...
this.render('myTemplate');
},
onAfterAction() {
// perform action after route loads
// ...
}
});
From the official guide, there are a number of options available to perform functions at router level, depending on exactly when you want the action to initiate:
Available Hook Methods
onRun: Called when the route is first run. It is not called again if the route reruns because of a computation invalidation. This
makes it a good candidate for things like analytics where you want
be sure the hook only runs once. Note that this hook won't run
again if the route is reloaded via hot code push. You must call
this.next() to continue calling the next function.
onRerun: Called if the route reruns because its computation is invalidated. Similarly to onBeforeAction, if you want to continue
calling the next function, you must call this.next().
onBeforeAction: Called before the route or "action" function is run. These hooks behave specially. If you want to continue calling
the next function you must call this.next(). If you don't,
downstream onBeforeAction hooks and your action function will not
be called.
onAfterAction: Called after your route/action function has run or had a chance to run. These hooks behave like normal hooks and
you don't need to call this.next() to move from one to the next.
onStop: Called when the route is stopped, typically right before a new route is run.
Plugins:
If you want to reuse the same functionality on multiple routes, you can create route plugins like this:
Iron.Router.plugins.loading = function (router, options) {
// this loading plugin just creates an onBeforeAction hook
router.onBeforeAction('loading', options);
};
Take a look at the full guide to try more hooks and methods that may be useful to you.

Related

How to handle subscription in Meteor / Iron Router

whats the bestway to handle subscription based data. For example, you have a game where you have to create the character first before you can do any other things. Currently I thougth I can try to handle it with a onBeforeAction filter. So I have a global controller for every route that needs a the character.
DefaultController = LayoutController.extend({
onBeforeAction : function() {
var currentCharacter = Character.getCurrent.call({});
if(currentCharacter === undefined) {
this.render('CharacterCreate');
} else {
this.next();
}
},
waitOn() {
this.subscribe('characters.owned');
}
});
You have a route like this:
Router.route('/game', { controller: 'DefaultController' });
The problem is until the the collection is loaded the game template will shown. Is there a better approach like this? And another problem when a route needs a character it throws an exception until the subscription is loaded.
Just use a loading hook while the subscriptions are being loaded.
loading(){
this.render('myLoadingTemplate');
}
The loading hook is run automatically while waiting for subscriptions to be ready.
You might find my post on building a clean router.js file useful.

waitOn blocking template from loading

When I start the Meteor server and navigate to my default route, I see the AppLoading template inside MainLayout (as expected), but the main template never loads even after the subscription is loaded.
I've got a really simple routes.js file (below)
autopublish is still turned on.
I seeded the db and can confirm in the browser console that the subscription is there, and there are items in my Services collection.
Probably missing something really simple here.
/*===================
CONFIGURE DEFAULTS
====================*/
Router.configure({
layoutTemplate: 'MainLayout',
loadingTemplate: 'AppLoading',
notFoundTemplate: 'NotFound'
});
/*===================
CONFIGURE ROUTES
====================*/
Router.route('/', { // DEFAULT ROUTE
name: 'main',
template: 'Main',
waitOn: function() {
return Meteor.subscribe('services');
},
data: function() {
return Services.find();
}
});
I'm guessing you do not have a publication? The client is waiting for a "ready" notification from the publication and is not receiving it, hence nothing is loaded. Remove autopublish and start writing publications.
The autopublish package literally just copies the server DB to the client. You can't subscribe to anything if you do not actually have any publications.

iron:router Meteor how to change route (save state in history) without changing the url

I am developing a meteor applicaton . For routing I am using iron:router .
I am changing some templates by changing a session variable.
Is there any way that without changing the url the user gets an entry in the browser history, that with a browser back the session variable changes back?
My Problem is: Some beta testers tested the app and tried to close some overlays they opened with the browser back button.
I'm not sure I understand your question 100%. But it sounds like you want to set a session variable to a specific value based off of a specific route to control the state of an overlay?
If that's the case, your best bet would be to use an onBeforeAction hook.
Here's how you could do that with a Route Controller:
PostController = RouteController.extend({
waitOn: function () {},
data: function () {},
onBeforeAction () {
Session.set('someSession', 'someValue');
},
action: function () {
this.render();
}
});
If you don't want to use a Route Controller, you can also just add a hook function and specify a route for which the hook should run on.
Edit
Router.onBeforeAction(function () {
Session.set('showOverlay', false);
this.next();
});
You can also specify routes that you don't want this before hook on:
Router.onBeforeAction(function () {
Session.set('showOverlay', false);
this.next();
}, { except: ['admin'] });

Iron Router onBeforeAction isn't being called

I have a /user route set up, which is supposed to render the login template if the current user isn't logged in. The entire router has a waitOn that waits for the currentUser subscription to finish. The problem is that when I go to /user it simply renders the dataNotFound template instead.
Here's the snippets of code that are relevant to this situation. I've been careful to show you them in the order they're defined in my lib/router.js file.
Router.plugin('dataNotFound', {notFoundTemplate: 'notFound'});
Router.onBeforeAction(function () {
console.log(Meteor.userId())
if (!Meteor.userId()) this.render('login');
else this.next();
}, { only: ['user'] });
Router.configure({
waitOn: function () { return Meteor.subscribe('currentUser'); }
});
Router.route('/user', {
name: 'user',
template: 'userView',
data: function () { return Meteor.user(); }
});
That console.log above doesn't even ever fire. It seems to me that since it should be a reactive function that even if initially the dataNotFound is rendered, then soon after that the onBeforeAction should be fired and render the login template, right?
It's very bizarre that your console log doesn't even fire. I have a few ideas, but first want to address the last piece of your question.
The dataNotFound plugin is triggered when the data function fires on your rout. This means it is bypassing your onBeforeAction hook altogether, and not that it isn't getting there.
One thing I can think of that might be worth trying would be wrapping the 'user' route action in a if ( this.ready() ) statement:
edit:
Router.route('user', {
// Your other stuff
action: function() {
if this.ready() {
this.render();
},
The reason I suggest this is just that you are using a waitOn statement, but I'm not 100% sure how that works if you don't have a this.ready() somewhere in your route, because that's what (again, from my reading of the documentation, have not fiddled around with it) tells the router what to wait before executing. Possibly it's not waiting at all right now.
I had a problem with onBeforeAction hook after upgrading from meteor 0.9.1 to 1.
It didnt get fired when it should. Like after I log out, I enter address manually and instead of login page I can see the actual site waiting for data that never comes. onRun hook solved it, but as docs says it gets fired only once.
Router.onRun(function () {
if (!Meteor.userId()) {
this.render('login');
} else {
this.next();
}
}, { only: ['user'] });
Try swapping out Meteor.userId() with Meteor.user() in your if statement. See this link for reference on how to handle checking for the user in a before filter: http://www.manuel-schoebel.com/blog/meteorjs-iron-router-filters-before-and-after-hooks.
I found the issue here.
According to this post, thanks to Steeve Cannon. The problem is on waitOn function.
Probably when you logginOut the subscribe to currentUser will fail, and this will make your app in infinite waiting. onBeforeAction runs after waitOn
You will need to check all variables in you Publish to insure waitOn complete successfully.
Put an if statement inside the waitOn function.
waitOn: function () {
if(Meteor.userId())
return Meteor.subscribe('currentUser');
}
Refer this comment to know why this is happening: https://github.com/iron-meteor/iron-router/issues/1010#issuecomment-72210587

meteorjs - force iron-router to wait the render of all until waitOn finished

I am looking for a way to wait before rendering anything when a waitOn argument is given.
Currently it works perfectly with the recommended way:
use onBeforeAction ('loading')
use action : function (if (this.ready()) this.render())
waitOn : function () {return [Meteor.subscribe()...]}
So when rendering the routing template the render process waits. But when I include a Template in the main-template the "sub"-Template will be rendered BEFORE the waitOn options ends.
So what is the recommended way to tell the iron-router to wait for the waitOn ready-state before render all included templates and also all yield-sub-templates ?
For me this works great:
this.route('note',{
path: '/note/:_id',
waitOn: function() { return Meteor.subscribe('notes')},
data: function() {
if( this.ready() ){ this.render();
return Notes.findOne(this.params._id);
}else{this.render('loading') }}
});
No content flashing or anything.
But also would like to know of how the guru's deal with it.

Resources