Doing something different for main route in meteor iron router - javascript

Im using Iron-Route for routing in my meteor app. As I have multiple modules and I want to avoid multiple coding, I put the filter for authentification (role) to the core package:
core package
var filters = {
authenticate: function () {
var user;
if (Meteor.loggingIn()) {
this.layout('login');
this.render('loading');
} else {
user = Meteor.user();
if (!user) {
this.layout('login');
this.render('signin');
return;
}
this.layout('StandardLayout');
this.next();
}
}
}
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
notFoundTemplate: 'notFound',
before: filters.authenticate
});
Router.route('/', function () {
this.render('contentTemplate', { to: 'content' });
this.render('navigationTemplate', { to: 'navigation' },)
});
other packages
...just need this:
Router.route('/article/:_id', {
name: 'article',
yieldTemplates: {
'navigationPage': { to: 'navigation' },
'contentPage': { to: 'content' }
}
});
Now there is a check on every module (route) before displaying anything.
But I need an exception for the front page. The main page Route.route('/') should be accessed also by user who are not logged in. How do I do that?

You can use the onBeforeAction hook from iron:router as shown below.
This solution assumes your login route is named 'login' . But can be modified to fit your needs.
./client/lib/hoooks/router.js
Router.onBeforeAction(function () {
// all properties available in the route function
// are also available here such as this.params
if (!Meteor.userId()) {
//code for action to be taken when user is not logged in
this.redirect('login');
this.stop();
} else {
this.next();
}
},{except: ['homeRouteName'] });
NB: Replace 'homeRouteName' with the name of your route at '/'

Related

Using iron-router to go to a certain id section of the page (url#portion) in Meteor.js

I have routes set up with iron-router that make sure the page goes to the top of the page:
Router.route('/services', {
name: 'services',
template: 'services',
onAfterAction: function () {
scrollTop();
}
});
function scrollTop() {
window.scroll(0, 0);
}
However, if I am on another route, and I have a link like /services#thisid
it will still take me to the top of the page (not to the portion of the page with the id=thisid).
Is there a way to get around this?
This should address your issue both for this issue and your layout override question.
Router.configure({
layoutTemplate: 'main',
onAfterAction: function(){
console.log('hash', this.params.hash);
if(!this.params.hash){
scrollTop();
}
}
});
Router.route('/services', {
name: 'services',
template: 'services',
});
Router.route('/inquiry', {
name: 'inquiry',
template: 'inquiry',
layoutTemplate: 'alternate'
});
The check for this.params.hash ensures that there is no value for the hash before executing the scrollTop. The layoutTemplate on the inquiry route overrides the layout while still respecting the global onAfterAction.

How do I debug this flickering URL Router.go issue in Meteor?

I wish I can give a more detailed response, but I can't even figure out how to debug this situation.
The situation: When I click on the button, the URL changes for a split second to http://localhost:3000/register. Nothing new gets rendered, the page stays the same as if I didn't click anything. Things I've tried:
Typing in Router.go('/register') in the console works properly
I have tried this with every single route, not just the /register route
I have tried this in both Firefox and Chrome
This is not an issue if I use {{pathFor 'templateName'}} in the template, only when I use Router.go('path')
I have a link in my header to register:
Template.header.events({
'click .register-btn': function(e) {
Router.go('/register');
}
});
And, of course, I have this in my template:
Contact
Here is my entire routing file, router.js:
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
notFoundTemplate: 'notFound'
});
// Routes
Router.route('/', {
name: 'landingPage', // Main domain routing
layoutTemplate: 'landingLayout',
onBeforeAction: function (pause) {
if (Meteor.user()) {
Router.go('/home');
} else {
this.next();
}
}
});
Router.route('/home', {
name: 'siteHome',
onBeforeAction: function() {
if (this.ready()){
if (!Meteor.loggingIn())
AccountsTemplates.ensureSignedIn.call(this);
}else{
// render the loading template but keep the url in the browser the same
this.render('loading');
this.renderRegions();
}
}
});
Router.route('/weekly_goal/set', {
name: 'setWeeklyGoal'
});
Router.route('/make_entry', {
name: 'makeEntry'
});
// Login and Register Routes
AccountsTemplates.configureRoute('signIn', {
name: 'login',
path: '/login',
template: 'siteLogin',
});
AccountsTemplates.configureRoute('signUp', {
name: 'register',
path: '/register',
template: 'siteRegister',
redirect: '/',
});
When you click a button inside of a form, the default browser behavior is to submit the form which causes another HTTP request and reloads the page. In order to avoid this, your event handler needs to explicitly prevent the default behavior:
Template.header.events({
'click .register-btn': function(e) {
e.preventDefault();
Router.go('/register');
}
});

Meteor.js Iron Router and similar or dynamic routes

I am trying to build dynamic routes for an admin section on my site so that "/admin" would work as well as "/admin/users" and "/admin/users/add" and so on. I have tried some different combinations but still struggling with this. Below is what I've tried and in different orderes.
Ideally if I could just specify "/admin" but dynamically reference each new / as an argument that would be best for handling in the code. Example "/admin/1/2/3/4/5" and being able to reference the 1 2 3 etc. I didn't see anything like this in the docs though.
Router.route('/admin', {
name: 'admin',
path: '/admin',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
Session.set('apage', 'dashboard');
Session.set('asect', null);
this.render();
}
});
// Not Working...
Router.route('/admin/:apage', {
name: 'admin',
path: '/admin/:apage',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
Session.set('apage', this.params.apage);
Session.set('asect', null);
this.render();
}
});
// Not Working...
Router.route('/admin/:apage/:asect', {
name: 'admin',
path: '/admin/:apage',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
Session.set('apage', this.params.apage);
Session.set('asect', this.params.asect);
this.render();
}
});
EDIT (Answered)
After some testing it seems calling a template should be (or easiest done) in the this.render() line and the routes should go from most restrictive/detailed to least - which I did try before. The problem seems to be using this.params on the template: line. This solution is not perfect but posting for anyone who may run into a similar problem. As far as further variables in the url like "/admin/1/2/3/4/5" it seems they would need additional routes and can't be fully dynamic as a "/" can not go into the params and the router would look for a route and return notFound unless you can an explicit matching route. There may be a work around that I did not find.
Working code below:
Router.route('adminPage', {
path: '/admin/:asect/:apage',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
Session.set('asect', this.params.asect);
Session.set('apage', this.params.apage);
this.render('admin_' + this.params.asect + '_' + this.params.apage);
}
});
Router.route('adminSect', {
path: '/admin/:asect',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
Session.set('asect', this.params.asect);
Session.set('apage', null);
this.render('admin_' + this.params.asect);
}
});
Router.route('admin', {
path: '/admin',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
Session.set('asect', 'dashboard');
Session.set('apage', null);
this.render('admin_dashboard');
}
});
There is a way to have optional parameters in routes (which is what you're looking for unless I'm mistaken). With that in mind, you should be able to manage using one router.
Router.route('admin',{
path: '/admin/:asect?/:apage?',
template: 'admin',
layoutTemplate: 'layout_admin',
action: function() {
var asect = this.params.asect || 'dashboard',
apage = this.params.apage || null,
render = (function(){
if(apage !== null) {
return 'admin_'+ asect +'_'+ apage;
} else {
return 'admin_'+ asect;
}
})();
Session.set('asect', asect);
Session.set('apage', apage);
this.render(render);
}
});
The ? after each parameter in the path designates it as an optional parameter. You should be able to then check if it has been defined or otherwise assign a default value and then structure your view and session accordingly.
Note: You can test in this MeteorPad - just update the URL according to the names of the example templates.
http://meteorpad.com/pad/Ri4Np5xDJXyjiQ4fG

ReactJS redirect

I'm using ReactJS and react-router in my application. I need to do next thing: when user open the page - to check, if he logged in or no, and if yes, then to do redirect to /auth page. I'm doing next thing:
componentWillMount: function() {
if (sessionStorage["auth"] == null) {
this.transitionTo("/auth");
}
},
In browser url it really do redirect to /auth, render the /auth page and after override it with current component. So here the question: how to cancel rendering for the current component, or how to do redirect in other way? Thanks.
Take a look at the react-router example auth-with-shared-root: https://github.com/rackt/react-router/tree/master/examples/auth-with-shared-root
What they basically do is to check on an enter of a route where to go. Take a look in file config/routes.js line 36, 51 and 89:
{ onEnter: redirectToLogin,
childRoutes: [
// Protected nested routes for the dashboard
{ path: '/page2',
getComponent: (location, cb) => {
require.ensure([], (require) => {
cb(null, require('../components/PageTwo'))
})
}
}
// other protected routes...
]
}
This route will call function redirectToLogin when the route /page2 is entered or pushed to. The function can than check, if the user is authenticated with auth.loggedIn()
function redirectToLogin(nextState, replace) {
if (!auth.loggedIn()) {
replace({
pathname: '/login',
state: { nextPathname: nextState.location.pathname }
})
}
}
If the user is not logged in, the function will replace the route to /login, where the user can authenticates itself.

Ember.js Error in specifying URL type of location='history' in App.Route

I have started learning the ember.js framework and I am stuck at how to use the setting of the URL type feature that the framework has.
http://emberjs.com/guides/routing/specifying-the-location-api/
I have this simple application.js
App = Ember.Application.create();
App.Router.reopen({
location: 'history'
});
App.Router.map(function () {
this.route('about');
});
App.ApplicationRoute = Ember.Route.extend({
model: function () {
return appdata;
}
});
App.IndexRoute = Ember.Route.extend({
setupController: function (controller) {
// Set the IndexController's `title`
controller.set('indextitle', "My Index title");
},
renderTemplate: function () {
this.render({ outlet: 'indexoutlet' });
}
});
App.AboutRoute = Ember.Route.extend({
model: function () {
return appdata;
},
renderTemplate: function () {
this.render({ outlet: 'aboutoutlet' });
}
});
var appdata = { mytext: '', theplaceholder: 'Enter new text', attr:'Yeap!' }
If I don't use the
App.Router.reopen({
location: 'history'
});
the application works fine and it goes to the 'about' route by appending the URL the '~/EmberjsTest.aspx#/about' as it supposed to do.
However because I do not like the hash symbol in the URL of the page, I would prefer if it was removed and to do that the guide says we should put this code:
App.Router.reopen({
location: 'history'
});
But when I do it I get an error in the Chrome console saying:
'Assertion failed: The URL '/EmberjsTest.aspx' did match any routes in your application'
What am I doing wrong?
Thanks in advance
If you want to use the history API then you have two options.
Serve your Ember app from '/' so that Ember can just work with it's "normal" index/root route.
Create a route in your Ember app that can handle '/EmberjsTest.aspx'.
this.route("index", { path: "/EmberjsTest.aspx" });
Note that if you go with option 2 you'll probably have to update all of your routes to include '/EmberjsTest.aspx' in their paths.
this.resource("posts", {path: "/EmberjsTest.aspx/posts" })

Categories