0

I'm trying to write a simple method that will return the email (or any other field) of a logged in user. I have autopublish turned off but whenever I try to access Meteor.user() in my displayField method I get undefined.

However, if I write a general function (outside of Meteor) it can access it and display it fine... what am I doing wrong??

Meteor.methods({
displayEmail: function () {
 var user = Meteor.user();
 if (!user)
  throw new Meteor.Error(401, "you need to be logged in");
 console.log(user.emails[0].address);
 return user.emails[0].address;
}
 });

My client side function:

Template.hello.greeting = function () {
 var output = Meteor.call('displayEmail', function(error,id) {
 if (error) 
   return alert(error.reason);
 });
 return output;
 };

My template: ... {{greeting}} ...

So like I said, the console.log(user.emails[0].address) works just fine, but I get a blank in my template...

Jason Ip
  • 353
  • 1
  • 6
  • 16
  • 1
    Could you post your code and what version of Meteor you are using? This works fine for me on 0.6.6.3. – go-oleg Dec 10 '13 at 04:15
  • 1
    Your call to `Meteor.call` is asynchronous which is why `output` is null. The email address you are looking for is available in `id` in your callback. To get it into your template, take a look at these similar questions w/answers: http://stackoverflow.com/questions/16540328/meteor-template-helper-conditional-returns-false-consistently and http://stackoverflow.com/questions/16632050/meteor-return-asynchronous-function-to-handlebar-template. – go-oleg Dec 10 '13 at 05:24
  • I had a feeling it had something to do with that... do you have any links to read up on with regards to asynchronous/synchronous? – Jason Ip Dec 10 '13 at 15:24
  • [Meteor docs section](http://docs.meteor.com/#meteor_call_). You can google around for stuff like "javascript asynchronous callback patterns". Heres an SO [answer](http://stackoverflow.com/a/19083385/2359560) that has some good explanations. As you read more about callbacks and asynchronous programming, you'll run into terms like "callback hell" and ways to get around them using things like [async](https://github.com/caolan/async) and Promises. Perhaps its good to keep in mind that one of the cool things about Meteor is that it lets you do asynchronous things as if they were synchronous. – go-oleg Dec 10 '13 at 20:13

2 Answers2

0

With autopublish off, you would have to actually publish the user in order to access that data.

Autopublish would automatically publish it for you, but is generally a bad idea for production usage. When you turn it off, you have told Meteor that you will handle all of the publishing necessary.

Example:

Meteor.publish("currentUser", function () {
    return Meteor.users.find({_id: this.userId});
});
JC.
  • 670
  • 3
  • 12
  • well this is weird.. I have autopublish off and I have no Meteor.users publish or subscribe activated but if I go console.log(Meteor.user()..) in my Meteor.methods it will show. – Jason Ip Dec 10 '13 at 04:45
  • The `accounts-base` package publishes the current user (only username, emails, and profile fields) regardless of autopublish. It auto publishes other users if the autopublish packages is used. See [lines 562-635 here](https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_server.js#L562). – sbking Dec 10 '13 at 04:58
  • but why can't I return the user email from the method? I can get it to console.log from the method but I can't get it to output in my client function... – Jason Ip Dec 10 '13 at 04:59
0

Just answering my own question, so go-oleg is correct, with an async call you need the callback function in Meteor.call to get the variable back.

So my Meteor.call part should look like:

Meteor.call('displayEmail', function (error, result) {
   Session.set("displayEm",result);
 }); 
 return Session.get("displayEm");

In other words, the callback function needs to set a Session variable (which is reactive). The 'return' on the Meteor.method is the 'result' of the callback function (basic JS, I know).

Jason Ip
  • 353
  • 1
  • 6
  • 16