Folks, I am making progress, but I am certain that there is a better, more elegant way to accomplish this functionality. As before, I want users to "always" be directed to a welcome page once they log into the application, even if they were previously signed-out at a different page. What trips me up is the "this.next()" requirement for iron Router's onBeforeAction.
Briefly a scenario:
1) User navigates to the application and is prompted with a "Welcome but please sign-in/up" page.
2) User signs in, and the router directs the user to a "welcome to the application" page
3) User navigates through the application to "pageOne" and then decides to sign out, and is again presented with the "Welcome but please sign-in/up" page being rendered. (However, the URL still reads http://xxx.xxx.xxx.xxx/pageOne)
4) User signs-in again, where now the application should instead of rendering the "pageOne" page, which is the behavior of this.next(), be presented with the "welcome to the application" page.
I was able to get to this functionality with the code below:
Router.configure({
layoutTemplate: 'layout',
});
Router.route('/', {name: 'welcome'});
Router.route('/pageOne', {name: 'pageOne'});
Router.route('/pageTwo', {name: 'pageTwo'});
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn()) {
Router.go('welcome');
} else {
this.render('welcomeButLogin');
}
} else {
this.next();
}
}
Router.onBeforeAction(requireLogin, {except: ['blah']});
This works, but I am getting a warning message of:
Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?
Thank you for taking the time, any feedback would be much appreciated.
Gene.
Problem solved.
I changed:
Router.onBeforeAction(requireLogin, {except: ['blah']});
to:
Router.onBeforeAction(requireLogin);
per suggested code by solarc on the meteor forum (thanks solarc). I don't quite understand how this changes the routing specific behavior, since I interpreted that "{except" ['blah']}" would mean all routes since I did not have a "blah" route. I'll investigate further, but for now it works as expected, and I am not getting the warning message.
Thanks!
Related
I don't know why, the logout button in my Meteor App often fails to callback. the code is simple:
$scope.logout = function () {
Accounts.logout(function () {
// the code often fails to come here
$state.go('login');
});
}
maybe the network's problem? so I added some code to ensure my logout button won't look like frozen:
$scope.logout = function () {
Accounts.logout(function () {
// the code often fails to come here
$state.go('login');
});
$timeout(function () {
$state.go('login');
}, 2000);
}
The redirection to login page succeeded, but because Meteor.userId() still have value, the login page still shows the App user someone is logged on.
I want to know if there is a way to delete Meteor.userId / Meteor.user family even when failed connecting to the server.
I know it is not a complete solution, the App user will probably failed to do the next login at that state, but at least they won't complain the App even cannot logout.
The function you're looking for is Meteor.logout() not Accounts.logout()
I have set some functions in the template's onRendered hook like this :
Template.PanelLayout.onRendered(function() {
Tracker.autorun(function() {
if (ready.get()) {
page = Pages.findOne({
slug: 'about'
});
tinymce.init({
selector: "#pageContent",
height: 400
});
tinymce.get('pageContent').setContent(page.content);
}
});
});
If I visit that page directly or reload that page these functions will work. But if I visit it by just clicking a link in the navigation, the functions won't load. How can I fix this?
The short answer is you can't because this is how FlowRouter works:
FlowRouter docs
For a single interaction, the router only runs once. That means, after you've visit a route, first it will call triggers, then subscriptions and finally action. After that happens, none of those methods will be called again for that route visit.
What you are doing seems to be more suited for Meteor's Template helper
I'm trying to show a popup or a template page if user has signed in for the first time after sign up basically allowing them configure some stuff on that page before going to dashboard home, It's only needed for convenience and here is what I got (telescope code)
Router.onBeforeAction(hasCompletedChannels);
hasCompletedChannels: function() {
if(!this.ready()) return;
var user = Meteor.user();
if (user && ! userCompletedChannels(user)){
this.render('connectChannels');
} else {
this.next();
}
}
Which I don't really like because this will always run every time, I want it to run just once, And don't even execute the check function. Is it possible to detect first sign in? (After signup)
I think you could just tie it to the specific route. Right now you're tying it to the Router object (every render forces that check as you point out). So if you define your login function to send someone to a specific route after sign-in, you could just verify on that route.
The function Accounts.onLogin gives you a way to do stuff after the login.
Something like
Router.route('profile', {
path: '/profile',
onBeforeAction: function() {
// Check some stoof
// If first time logged in
// render first time template
// else
// this.next() will render the profile page
},
waitOn: function() {
return [
// some subs
];
},
data: function() {
// some data
}
});
I'm assuming that its going to get routed to a page called profile (seems to make sense). You could check for first time logged in by some attribute you use in the user object and the fields you want filled out and force a render of a different template, or a subtemplate. Check out the Iron Router guide for more ideas on ways to configure it.
Best of luck
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
I've asked this before, but in a different way, so I'm hoping asking it like this could get an answer :)
What API call results in this following dialog appearing:
http://dl.dropbox.com/u/222489/publishdialog.png
By using the FB.ui({method: 'stream.publish' ... function all I get is a "Post to Your Wall" dialog, and all great Facebook games get the dialog in the screenshot. So I must be using the wrong function.
I don't understand how you've missed it, it's the first snippet of code in the FB.ui documentation:
FB.ui(
{
method: 'feed',
name: 'Facebook Dialogs',
link: 'http://developers.facebook.com/docs/reference/dialogs/',
picture: 'http://fbrell.com/f8.jpg',
caption: 'Reference Documentation',
description: 'Dialogs provide a simple, consistent interface for applications to interface with users.',
message: 'Facebook Dialogs are easy!'
},
function(response) {
if (response && response.post_id) {
alert('Post was published.');
} else {
alert('Post was not published.');
}
}
);
Result in my test app:
Its known as a Feed Dialogue.. its one of the Three Facebook Dialogues that use user interaction for doing some work...
ItI dosent need a API call (It was possible with Facebook.showFeedDialog but now facebook dosent support it) instead u redirect the user to the Url for these dialogues.
http://www.facebook.com/dialog/feed?<your different attributes as quesry string>
For having this in your own page you Can open it in an iFrameby setting attribute display=iframe but you need an access token for that..
Here is a complete description..
http://developers.facebook.com/docs/reference/dialogs/feed/