Reputation: 813
On the client I want to render two different layouts.
Router.route('/', {
template: 'register',
layoutTemplate: 'home'
});
Router.route('/main', {
layoutTemplate: 'layout'
});
In this case only the first Router.route function works. What seems to be the problem in this code example?
In the console, this error pops up:
Exception in defer callback: TypeError: Cannot read property 'handler' of undefined
Additionally I don't want users to access the 'main'-template if they are not logged in. The iron:router documentation doesn't provide me enough information on how to handle both these issues.
Upvotes: 3
Views: 2711
Reputation: 1495
I definitely think that the issue with your routing code above is the fact that you have not specified a value for the template
attribute of your route with the path '/main'
. At the very least, I would suggest that you define that attribute if nothing else for a given route. The first thing that iron-router will attempt to do to determine which template to use for the route is to look at the path of the URL, and that is not always obvious to determine for a given route. I would suggest defining your routes above like so:
Router.route('/', function() {
template: 'register',
layoutTemplate: 'home'
});
Router.route('/main', function() {
template: 'main',
layoutTemplate: 'layout'
});
With this routing logic defined, you would then also want to make sure to define your templates properly.
For your layout templates, do something like the following:
<template name="home">
{{> yield}}
</template>
<template name="layout">
{{> yield}}
</template>
The {{> yield}}
parts are necessary here in the layout templates because that is where iron-router will render the template that you have defined for the route through the template
attribute.
For your regular templates, do something like the following:
<template name="register">
<h1>Register</h1>
</template>
<template name="main">
<h1>Main</h1>
</template>
After doing this, do your routes work? Alternatively, you could use Route.configure
to set global route attributes, or a series of RouteController
objects to define your routes so that common routes can take advantage of common attribute definitions.
As for your second issue, I would suggest using one of the two following methods:
In order to define your described logic for just the '/main'
route, do the following:
Router.route('/main', function() {
template: 'main',
layoutTemplate: 'layout',
onBeforeAction: function() {
if(!Meteor.userId()) {
this.render('register'); // Use either this one
this.redirect('register'); // or this one
} else {
this.next();
}
}
});
Going with this option will require that you add an additional attribute to your '/'
route, name: 'register'
. Alternatively you can directly reference the actual URL path of the desired route in the this.render()
or this.redirect()
function calls and then you do not have to define the name
attribute for your templates. Personally, I prefer being obvious and open with my route definitions by giving them all names and referencing them using their names.
The second option is to define your desired logic globally so that it applies not only to the '/main'
route, but to any other routes that you happen to define in the future as well. To do this, do the following:
Router.onBeforeAction(function() {
if(!Meteor.userId()) {
this.render('register'); // Use either this one
this.redirect('register'); // or this one
} else {
this.next();
}
},
{
except: ['register']
});
Once again, this option requires the definition of the name
attribute for your '/'
route, but you can do what I described above if you prefer not to do that. Finally, notice the except
attribute definition at the end of this option. This notifies iron-router to not run this globally-defined logic for the array of specified routes. Obviously, you would not want to run this logic on the very page to which you are redirecting users who are not currently logged in, hence my except
attribute definition above.
Upvotes: 3
Reputation: 11376
This is how your routes should look.
//Layout Configuration.
Router.configure({
layoutTemplate:"register"
});
Router.configure({
layoutTemplate:"layout"
});
//Simple Routes Config.
Router.route('/', {
layoutTemplate: 'register'
});
Router.route('/main', {
layoutTemplate: 'layout'
});
And The /client/views/layout.html
<template name="layout">
{{> yield}}
</template>
<template name="register">
{{> yield}}
</template>
Upvotes: 4
Reputation: 514
My guess is you need to define the template for the '/main'
route as well--that would be what is undefined
in your error. If you have a template with the name="main"
attribute, I would need to see more code, particularly any template handlers.
A redirect could be accomplished with the onBeforeAction
callback:
onBeforeAction: function() {
if (!Meteor.userId()) {
this.redirect('/');
} else {
this.next();
}
}
Upvotes: 0