Setting data that belongs to a User in iron router - meteor

Router.route('/settings', {
name: 'settings',
data: function() {
return Settings.findOne({userId: Meteor.user()._id});
}
});
It's showing an error in the browser:
Uncaught TypeError: Cannot read property '_id' of undefined
Any suggestions on how to grab the settings record for a logged in user?

Meteor logging in process usually takes a few ms to get ready, meanwhile Meteor.user() will return undefined and the first execution of your route data method will fail.
You can use Meteor.userId() to avoid this from happening until the user is connected for real.
Router.route('/settings', {
name: 'settings',
data: function() {
return Settings.findOne({
userId: Meteor.userId()
});
}
});

Related

Data from db undefined at first, then changes to actual data

I am doing a find on a collection of nodes and am then storing the info in a variable.
I am then console.logging this data to see the contents of it. The thing is, my data stays an empty array for a split second and then a new console.log is done with an array of data. See my code below:
Template.temperature.helpers({
node() {
let node = Nodes.find({_id:Session.get('selectedNode')});
console.log(node);
return '';
}
});
My console output:
1: []
2: [Object]
What could be the reason for this?
In your router, subscribe within waitOn:
Router.route('/home', {
waitOn: function() {
return [
Meteor.subscribe('nodes'),
];
},
action: function() {
if (this.ready()) {
this.render();
}
},
});
This will ensure that the route will wait until the subscription is completed before executing the route. It uses the meteor loading hook, so the wait will utilize whatever loading screen or animation you ahve setup.

meteorjs meteor-user-status mizzao package: cannot get other users

Trying to implement mizzao/meteor-user-status user status package, but only getting the status for the currently logged in user (me). Others show undefined.
Code in /server folder:
Meteor.publish('userStatus', function() {
return Meteor.users.find({
"status.online": true
});
});
Code in /client folder:
Meteor.subscribe('userStatus');
Template.member.helpers({
isOnline: function(username) {
console.log(username); //gets each username, not just logged me logged in
var currentUser = Meteor.users.findOne({
username: username
});
console.log(currentUser.status.online); //gets undefined for other users other than me
return currentUser.status.online; //returns undefined for other users
}
});
Maybe this needs to reference "userStatus" somehow instead of Meteor.users.findOne(...), but since global object was not created, e.g. like UsersOnline = new Mongdb.Collection - I don't know how to implement this.
Getting error in Chrome debugging tool: TypeError: Cannot read property 'status' of undefined, obviously, it only gets currently logged in user.
Edit: To clarify: I get other users from a custom "profiles" collection in Mongo that I created specifically to overcome the issue of not being able to read "users" collection, due to security, I guess. So I get the list of profiles and supply the user name to this function that supposed to use mizzao package to see if they are online. Since the package reads from "users" collection, it only returns current user (me).
I would be totally OK if I could modify the package for it to write to my "profiles" collection, if someone suggests how to do that.
Another update:
I ran the count on the server, and it returns only one (me, I guess).
var cursor = Meteor.users.find({
"status.online": true
}, {
fields:{
_id: 1,
status: 1,
username: 1
// Any other fields you may need
}
});
console.log(cursor.count());
If you have a publication like this:
Meteor.publish('userStatus', function() {
return Meteor.users.find({
"status.online": true
});
});
it will return users that are online only. So you get undefined for users other than you, because they are not logged-in.
Try logging in as a different user at the same time (i.e. using different browser), and see whether you can now see the status of that user.
You can always change your publication to:
Meteor.publish('userStatus', function() {
return Meteor.users.find({}, {fields: {username : 1, status : 1}});
});
and you will get statuses for all users. But if you only need to check the "online" flag (i.e. you don't need other features of the package), it is better to only send data about the online users and consider not published user as offline.
I guess you trying to read users before subscription is ready.
Server:
Meteor.publish('userStatus', function() {
return Meteor.users.find({
"status.online": true
}, {
fields:{
_id: 1,
status: 1,
profile: 1,
username: 1
// Any other fields you may need
}
});
});
Client (you should return cursor, which will re-run once subscription is ready):
Meteor.subscribe('userStatus');
Template.member.helpers({
isOnline: function(username) {
console.log(username); //gets each username, not just logged me logged in
var cursor = Meteor.users.find({username: username});
if(cursor.count()){
var currentUser = cursor.fetch()[0];
if(currentUser.status && currentUser.status.online){
console.log(currentUser.status.online); //gets undefined for other users other than me
return currentUser.status.online; //returns undefined for other users
}
}
return {};
}
});

"Cannot read property 'username' of undefined" in a Meteor Route?

The page still renders as it should, but this appears in my console log.
Exception in callback of async function: TypeError: Cannot read
property 'username' of undefined
at null. (http://localhost:3000/router.js?39194109cc7760190c519a386d66c807ba19230c:48:9)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at onRerun (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:520:9)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at onRun (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:505:11)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at dispatch (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:448:3)
Which points to the line indicated below:
var OnBeforeActions = {
loginRequired: function() {
if (!Meteor.userId()) {
this.render('hello');
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
only: ['home']
});
Router.route('/', function() {
// this.render('homepage');
Router.go('/users/' + Meteor.userId());
});
Router.route('/users/:user_id', function() {
this.render('home', {
data: {
username: Meteor.users.findOne({
_id: this.params.user_id
}).username, // THIS LINE HERE
}
});
});
The idea is to redirect the user to his page if he is already logged in - and it appears to work as it should, but why am I getting this?
When the browser loads initially there will not be any data available (all the collections will be empty - until they are downloaded. Thus the result of the query Meteor.users.findOne({_id: this.params.user_id}) will be undefined.
This is the reason you can't read username out of undefined.
Since the query will re-run/it is reactive you just need to take account when it is null and it will sort itself out. user.username is only read if user is not null:
Router.route('/users/:user_id', function() {
var user = Meteor.users.findOne({_id :this.params.user_id});
this.render('home', {
data: {
username: user && user.username
}
});
});

What is wrong with my subscription method on my route?

Can someone see why the route is not subscribing to the publication. Profiles = new Meteor.Collection('profiles');
The mongo database does have documents in this collection, but the browser console still has a count of 0 in Profiles collection.
I am trying to tell the router, "subscribe to user-profile publication, when you are ready, render the 'profile' template. I also named the route 'profile.'
Now I have noticed that after typingsub = Meteor.subscribe('user-profile'); and then sub.ready(); I get the count of the collection. Otherwise the path is not subscribed. This behaviour has not occurred before.
lib/router.js
Router.plugin('loading', {loadingTemplate: 'Loading'});
Router.route('user/profile', {
name: 'profile',
waitOn: function () {
// return one handle, a function, or an array
return Meteor.subscribe('user-profile');
},
action: function () {
// this.ready() is true if all items returned from waitOn are ready
if (this.ready())
this.render('profile');
else
this.render('Loading');
}
});
server.js:
Meteor.publish('user-profile', function () {
return Profiles.find({userId: this.userId});
});
userId is a field in the Profiles collection. This profiles doc id is stored within the user.profile.experiences array for reference.
Meteor.userId is a function which returns the _id, not the _id itself, and you can't pass a function over DDP anyway. It should be:
waitOn: function () {
return Meteor.subscribe('user-profile', Meteor.userId());
}

Sending verification email with Meteor causing error

I have the following:
Template.joinTemplate.events({
"submit #Signup-Form": function(event, template) {
event.preventDefault();
var email = template.find('#Email').value;
Accounts.createUser({
username: template.find('#Email').value,
emails: {
address: template.find('#Email').value
},
password: template.find('#Password').value,
profile: {
firstname: template.find("#Firstname").value,
lastname: template.find("#Lastname").value
}
}, function(error) {
if (error) {
// Deal with errors
} else {
Accounts.sendVerificationEmail(this.userId, email);
Router.go('/');
}
});
}
});
But get the following error:
Error logging in with token: Error: You've been logged out by the server. Please login again. [403] debug.js:41
Exception in delivering result of invoking 'createUser': TypeError: Object #<Object> has no method 'sendVerificationEmail'
at http://localhost:3000/client/views/application/authentication/join_template.js?0ca175e5dc0f3b4596ed33e260d5636f8f9cc69b:28:26
at http://localhost:3000/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:801:19
at loggedInAndDataReadyCallback (http://localhost:3000/packages/accounts-base.js?efdcc57c69f7e2ccbb61f1e963da216b1729ac72:455:5)
at null._callback (http://localhost:3000/packages/meteor.js?2b578107b8239ff9bc64200e6af2a24001461b30:801:22)
at _.extend._maybeInvokeCallback (http://localhost:3000/packages/livedata.js?418d88f2513ae6bf0ff1447759a5c590923456bd:3502:12)
at _.extend.receiveResult (http://localhost:3000/packages/livedata.js?418d88f2513ae6bf0ff1447759a5c590923456bd:3522:10)
at _.extend._livedata_result (http://localhost:3000/packages/livedata.js?418d88f2513ae6bf0ff1447759a5c590923456bd:4452:9)
at onMessage (http://localhost:3000/packages/livedata.js?418d88f2513ae6bf0ff1447759a5c590923456bd:3376:12)
at http://localhost:3000/packages/livedata.js?418d88f2513ae6bf0ff1447759a5c590923456bd:2705:11
at Array.forEach (native)
I have all accounts-base, accounts-ui, accounts-password installed.
Not sure what I'm doing wrong :(
As you can read in the documentation, Accounts.sendVerificationEmail is only available on the server, and you're trying to use it on the client.
I'm not sure that you can use the Accounts.onCreateUser function to send verification emails: in this function, the user has not been added to the Meteor.users collection yet, and I guess Accounts.sendVerificationEmail requires the user to be in that collection. I don't know the best way to solve this, but you can always use a cursor selecting all users, and then observe users added to the collection (although, this is not a good solution).
It's not enough to use the sendVerificationEmail field in the Accounts.config function?

Resources