Meteor AccountTemplates/UserAccounts - how to run code on email verify? - meteor

I've got some code I want to run after the user verifies their email.
Where would I put that?
The only place I can think is a redirected route, but that's a bit hacky, and relies on the user waiting for the redirect to happen. I'm using iron-router.
This was my first attempt, but the recalculate function is server-side.
AccountsTemplates.configureRoute('verifyEmail', {
redirect: function(){
var user = Meteor.user();
if (user) {
user.recalculateSignUpReputation();
Router.go('home');
}
}
});
Here's a solution observing a cursor but that seems like overkill. I'd prefer an event. Solution #1 didn't work for me.

thanks for the comments. I ended up doing this.
AccountsTemplates.configureRoute('verifyEmail', {
redirect: function(){
var user = Meteor.user();
if (user) {
Meteor.call('recalculateSignUpReputation');
Router.go('home');
}
}
});
It works client side, and makes a call to the server-side code. Not awesome, but works. If you have a different/better way, I'll mark it the correct answer.

Related

How to clear Meteor's user even offline

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()

Meteor JS & Blaze - Show Only Once on Load

I have a partial that show's a notification modal to agree to the site's terms and service that I would only like to show once (once they click I agree it goes away).
Is there anyway to do that with Meteor?
Assuming you want to store a boolean in the DB indicating that the user has accepted the terms (so they never get asked again), you could add a field called hasAcceptedTerms somewhere on the user object (e.g. in the user's profile). Once you do that you could write your template like this:
<template name="myTemplate">
{{#if areTermsVisible}}
(put terms partial here)
{{/if}}
</template>
Where areTermsVisible looks like:
Template.myTemplate.helpers({
areTermsVisible: function() {
var user = Meteor.user();
return user && user.profile && !user.profile.hasAcceptedTerms;
}
});
And the code to record the acceptance looks like:
Template.myTemplate.events({
'click .accept-terms': function() {
var userId = Meteor.userId();
var modifier = {$set: {'profile.hasAcceptedTerms': true}};
Meteor.users.update(userId, modifier);
}
});
Maybe not surprisingly, the best way to deal with cookies policy notification is by using cookies. The problem is not meteor-specific, but there are at least two good atmosphere packages that can help you to deal with the problem:
https://atmospherejs.com/mrt/cookies
https://atmospherejs.com/chuangbo/cookie
What you need to do is basically, set cookie
Cookie.set('userHasAcceptedPolicy', true, { year: 1 });
with whatever arguments you like, and as soon as the user clicks the "accept" button. Then, before you decide if you need to show the policy notification you can use:
Cookies.get('userHasAcceptedPolicy');
to see if there's a need to do so. So it's pretty much the same solution as #DavidWeldon suggested but it does not require referencing the Meteor.user() object, so the user does not need to have an account to accept the policy.
Please note, that - at least in case of mrt:cookies - Cookies.get is a reactive data source, which is quite helpful when it comes to rendering templates.
There's plenty of ways...
This isn't a Meteor specific question.
Template.notifications.events({
'click #close-modal': function(e, t) {
$('#modal').hide();
}
})

How to prevent navigating to another page in meteor iron router

I have a form page and I want to alert user if he leaves it without saving the form.
Typically I can achieve this purpose by stating a function window.onBeforeUnload.
window.onBeforeUnload = function(){return 'Please save the form before navigating';}
But it seems doesn't work in my project using Meteor and Iron Router.
Any suggestion?
This is maybe a hacky version, but it works:
isUnsaved = ->
return unless #ready()
unless confirm 'Do you really want to leave the page?'
Router.go(#url)
Router.onStop isUnsaved,
only: [
'editPost'
]
Old post, but just solved it. Here is my solution :
Router.route('/myPath', {
unload: function (e, obj) {
if(Session.get("hasChanged")){
if (confirm("Are you sure you want to navigate away ?")) {
// Go and do some action
}else{
// Redirect to itself : nothing happend
this.redirect('/myPath');
}
}
}
}

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

Durandal: How to route away from current view within that view's activate() function?

I have the following:
function activate(routeData) {
// make dataservice call, evaluate results here. If condition is met, reroute:
if (true){
router.navigateTo("#/someRoute");
}
alert ("should not be shown");
}
The alert is getting hit however, and then the view changes.
How do I fully navigate away from the current item and prevent any further code in that vm from being hit?
Update:
I tried using guardroute but I have to activate the viewModel to call the dataservice that returns the data that determines whether or not I should re-route. Using guardroute totally prevents the dataservice from getting called (since nothing in the activate function will get hit).
I also tried returning from the if block but this still loads the view / viewAttached / etc so the UX is glitchy.
The following worked for me in Durandal 2.0:
canActivate: function() {
if(condition)
return {redirect: 'otherRoute'};
return true;
}
activate: // Do your stuff
It's mentioned in the documentation: http://durandaljs.com/documentation/Using-The-Router.html
Here's #EisenbergEffect answer to a quite similar discussion in google groups.
Implement canActivate on your view model. Return a promise of false,
then chain with a redirect.
You might want to give #JosepfGabriel's example (discussion) a try in Durandal 1.2. Check the correct router syntax for your Durandal version, you might have to substitute it with something like router.navigateTo("#/YourHash", 'replace').
canActivate: function () {
return system.defer(function (dfd) {
//if step 2 has a problem
dfd.resolve(false);
})
.promise()
.then(function () { router.navigate("wizard/step1", { trigger: true, replace: true }); });
}
However this is NOT working in Durandal 2.0 and there's a feature request https://github.com/BlueSpire/Durandal/issues/203 for it.
You can't call redirect into the active method.
You can override the guardRoute method from router, to implement redirections.
You can do somehting like that:
router.guardRoute= function(routeInfo, params, instance){
if(someConditios){
return '#/someRoute'
}
}
You can return a promise, true, false, the route to redirect... You can find more information about that in the next link: http://durandaljs.com/documentation/Router/
Rainer's answer was pretty good and works for me adding this small fix.
Inside the then() block simply call the navigation like this
setTimeout(function() { router.navigateTo('#/YOUR DESTINATION'); }, 200);
that should fix your problem. The setTimeout does the trick. Without it the newly navigated page catches the old NavigationCancel from the previous one.
Adding a return in your if (true) block should fix this.
function activate(routeData) {
if (true){
router.navigateTo("#/someRoute");
return;
}
alert ("should not be shown");
}

Resources