I'm following this fantastic tutorial on customizing login found as the answer on this post - http://goo.gl/VLO34 - but it's not working for me.
I copied all the files verbatim, and even added supplementary smart packages such as underscore _.pick, and http Meteor.http.get just in case it was required, and mistakenly left out.
Anyhoo - I get github to authorize my app, but Meteor.users in the web console and db.users.findOne() on the local mongo instance show that Accounts.OnCreateUser() didn't add any new information to my user profile [that I'm pulling in from github]. In other words, {{currentUser.profile.avatar_url}} and {{currentUser.profile.login}} won't reveal anything following that tutorial. So I get blank info on the screen.
I tried that screencasts first attempt, and noticed that {loginButtons}} returns values for {{currentUser.profile.login}}. I've reviewed the code many times for typos, but feel that something is quite off with Accounts.onCreateUser(fn)...
I'm using Meteor 0.5.7, and if anyone else has experienced this problem following that screencast, please let me know. Thanks,
EDIT: I've deployed the project to - http://rptest-customlogin.meteor.com/.
Author of the screencast here. And as of a few seconds ago, a new user on your site :-). So, it looks like login is working on your site. But I'm guessing what's happening in your app is the login info isn't available yet at the time of rendering or at the time you're printing to the console. The reason is that all of that info is being populated asynchronously. It takes a few seconds for the process to complete. If you're relying on Meteor.user().profile data in your templates you need to check first if the login process is still underway.
To do that, you can use either the Meteor.loggingIn() javascript function or the {{#if loggingIn}} handlebars block helper. That function is "reactive" which means once the result changes from true to false your UI will update. So the template might look something like this:
<template name="loginDependentWidget">
{{#if loggingIn}}
Logging In
{{else}}
{{currentUser.profile.avatar_url}}
{{/if}}
</template>
Does this help?
Might be a typo but Accounts.OnCreateUser(fn); should be Accounts.onCreateUser(fn);
Meteor docs: http://docs.meteor.com/#accounts_oncreateuser
And then another post on the same subject:
Meteor login with external service: how to get profile information?
EDIT:
Posting as edit due the formatting of the below piece of code.
In the meantime I have got it running on my own project with this piece of code:
Accounts.onCreateUser(function(options, user) {
if(!options || !user) {
console.log('error creating user');
return;
} else {
if(options.profile) {
user.profile = options.profile;
}
}
return user;
});
Which is working just fine. Have you placed the Accounts.onCreateUser(); on the server?
Related
I am working with offline support of Meteor Application. I have researched about this support but all are giving one answer 'ground:db'. I looked into that solution its really nice effort by #raix. I started with that package, Its already working project so first task i have done that all collection i have grounded with following syntax
var Users = Meteor.users;
if(Meteor.isClient){
SmtGroundCollections.Users = Ground.Collection(Users);
}
After that i have tried with my offline application but still its showing loading and i am not getting my dom elements after that i have tried with that all waitOn subscription i have put on condition
if(Meteor.status().connected){
/* my subscriptions */
}
After that i am able to see my dom and if i visited that page when i am online then after i am going offline i am able to see my data.
Now i am explaining my problems.
1) When i am calling my methods its not updating my ground collection if i am offline. I used below code for resume my methods
if(Meteor.isClient){
Ground.methodResume([
'addProfie',
' editProfile' ,
' deleteProfile ' ,
]);
}
Its working fine when i am coming from offline to online its syncing my data to server but i am not able to immediate effect.
2) If i want full application offline then i need to visit every page of my mobile application and then i can get that data in offline but its not possible so i want one centralise thing where i will press button and i can grounded my all data which i want offline.
So can anyone help me to solve above problem
Thanks in advance
How can I let the user know when they are getting a hot code push?
At the moment the screen will go blank during the push, and the user will feel it's rather weird. I want to reassure them the app is updating.
Is there a hook or something which I can use?
Here's the shortest solution I've found so far that doesn't require external packages:
var ALERT_DELAY = 3000;
var needToShowAlert = true;
Reload._onMigrate(function (retry) {
if (needToShowAlert) {
console.log('going to reload in 3 seconds...');
needToShowAlert = false;
_.delay(retry, ALERT_DELAY);
return [false];
} else {
return [true];
}
});
You can just copy that into the client code of your app and change two things:
Replace the console.log with an alert modal or something informing the user that the screen is about to reload.
Replace ALERT_DELAY with some number of milliseconds that you think are appropriate for the user to read the modal from (1).
Other notes
I'd recommend watching this video on Evented Mind, which explains what's going on in a little more detail.
You can also read the comments in the reload source for further enlightenment.
I can image more complex reload logic, especially around deciding when to allow a reload. Also see this pacakge for one possible implementation.
You could send something on Meteor.startup() in your client-side code. I personally use Bert to toast messages.
I'd like to use the utilities:avatar package, but I'm having some major reservations.
The docs tell me that I should publish my user data, like this:
Meteor.publish("otherUserData", function() {
var data = Meteor.users.find({
}, {
fields : {
"services.twitter.profile_image_url_https" : true,
"services.facebook.id" : true,
"services.google.picture" : true,
"services.github.username" : true,
"services.instagram.profile_picture" : true
}
});
return data;
});
If I understand Meteor's publish/subscribe mechanism correctly, this would push these fields for the entire user database to every client! Clearly, this is not a sustainable solution. Equally clearly, however, either I am doing something wrong, or I am understanding something wrong.
Also: This unscalable solution works fine in a browser, but no avatar icons are visible when the app is deployed to a mobile device, for some reason.
Any ideas?
Separate the issue of which fields to publish from which users you want to publish data on.
Presumably you want to show avatars for other users that the current user is interacting with. You need to decide what query to use in
Meteor.users.find(query,{fields: {...}});
so that you narrow down the list from all users to just pertinent ones.
In my app I end up using reywood:publish-composite to publish the users that are related to the current user via an intermediate collection.
The unscalability of utilities:avatar seems, as far as I can tell, to be a real issue, and there isn't much to be done about it except to remove utilities:avatar and rewrite the avatar URL-fetching code by hand.
As for the avatars not appearing on mobile devices, the answer was simply that we needed to grant permission to access remote URLs in mobile-config.js, like this:
App.accessRule("http://*");
App.accessRule("https://*");
Is there a way to get the previous page location before going to the next page in IronRouter?
Is there an event I can use to fetch this information?
Thanks in advance.
Since Iron Router uses the usual History API, you can just use the plain JS method:
history.go(-1);
or
history.back();
Edit: or to check the previous path without following it:
document.referrer;
You can achieve the behavior you want by using hooks.
// onStop hook is executed whenever we LEAVE a route
Router.onStop(function(){
// register the previous route location in a session variable
Session.set("previousLocationPath",this.location.path);
});
// onBeforeAction is executed before actually going to a new route
Router.onBeforeAction(function(){
// fetch the previous route
var previousLocationPath=Session.get("previousLocationPath");
// if we're coming from the home route, redirect to contact
// this is silly, just an example
if(previousLocationPath=="/"){
this.redirect("contact");
}
// else continue to the regular route we were heading to
this.next();
});
EDIT : this is using iron:router#1.0.0-pre1
Apologies for bumping an old thread but good to keep these things up to date saimeunt's answer above is now deprecated as this.location.path no longer exists in Iron Router so should resemble something like the below:
Router.onStop(function(){
Session.set("previousLocationPath",this.originalUrl || this.url);
});
Or if you have session JSON installed (see Session JSON)
Router.onStop(function(){
Session.setJSON("previousLocationPath",{originalUrl:this.originalUrl, params:{hash:this.params.hash, query:this.params.query}});
});
Only caveats with thisis that first page will always populate url fields (this.url and this.originalUrl there seems to be no difference between them) with full url (http://...) whilst every subsequent page only logs the relative domain i.e. /home without the root url unsure if this is intended behaviour or not from IR but it is currently a helpful way of determining if this was a first page load or not
I'm struggling to pass data from one template to another, and thinking about it I wonder if that's my problem anyway. I'm using the built in accounts system, I have adding new users and authentication working, and when a user signs in I forward them to a new template. I'd like to be able to use their details in that template but I'm struggling to figure out the best way to do this.
Initially I thought I could simply use: Router.go('userPage', {user:username}); which gives no errors but doesn't work. In my template I'm using : <p>Welcome {{user}}</p>
Using {{> user}} throws an 'Can't find template, helper or data context key: username' error.
Any ideas?
EDIT: Ignore the rest, after restarting the Meteor server this is now working.
Thinking I have a bigger issue here so adding more detail:
Taking some info from a form and then routing based upon the outcome:
Meteor.loginWithPassword(username, password, function(err) {
if (err) {
console.log('Logging in failed');
} else {
console.log('Logging in succeeded');
console.log(username);
Router.go('userPage');
}
});
I then wish to open this template and pass through the data of the user who just logged in:
<template name="userPage">
<div class="container">
<h1>Welcome {{username}}</h1>
</div>
<p>User Page</p>
</template>
If I use <p>Welcome {{currentUser.username}}</p> I get no errors but also no name. Meteor.user().username does return a name but I cannot get that into the template.
"username" is undefined, you should use Meteor.user().username
Or better yet, you should use the currentUser predefined helper which contains the currently logged in user that you can pass between pages.
<p>Welcome {{currentUser.username}}</p>
The usual way to pass data between templates is by transmitting the document _id in the route url then retrieving it with the Iron Router and doing your stuff with the doc.
Sometimes it is easier to store currentSomething in a global helper, with a reactive Session variable keeping track of the "something _id" but it can lead to pretty sloppy code, beware !