I have a Questions
collection, which I have defined using SimpleSchema in a file "collections.js", which is in questions > lib.
This collection has an askedBy
field. It is an array of Strings that stores the userIds of the people who asked the questions.
askedBy: {
type: [String],
optional: true
},
In another file, questions > server > publish.js, I have:
Meteor.publish("questions", function () {
questionList = Questions.find(
{},
{
fields: {
"_id": 1,
"questiontext": 1,
"createdAt": 1,
"askedBy": 1,
"slug": 1
}
}
);
return questionList;
});
My objective is to make the names of the users who asked the question available, i.e. the user names of the users corresponding to the Ids in the 'askedBy' array.
How do I do this?
Things I have tried so far:
In collections.js:
Questions.helpers({
askedByUsers: function() {
console.log("askedBy:");
console.log(Meteor.users.findOne(this.askedBy[0]));
return Meteor.users.findOne(this.askedBy[0]);
},
This fails because Meteor.users
seems to only have access to the currently logged in user details. For all questions asked by other users, it returns a null value.
So then I tried adding this to publish.js:
Meteor.publish("allUsers", function () {
return Meteor.users.find({},
{
"name": 1,
});
});
and Meteor.subscribe("allUsers");
to both collections.js as well as questions.js (which have all my template helpers and event handlers). I also changed the collection helper to:
Questions.helpers({
askedByUsers: function() {
console.log("askedBy:");
console.log(allUsers.findOne(this.askedBy[0]));
return allUsers.findOne(this.askedBy[0]);
},
But even that doesn't work.
What am I doing wrong, and how can I fetch the usernames of not-logged in users?
edit: just in case this is important - folder structure
├── client
├── modules
│ ├── admin
└── questions
├── client
│ ├── questions.html
│ └── questions.js
├── lib
│ ├── collections.js
│ └── methods.js
└── server
└── publish.js
...
The answer to this question has a lot of layers to it. Fundamentally, you'll want the users published for the question(s) being viewed.
One approach is to subscribe to all of the users. This won't scale, but it should give you a result. Let's fix the code above to make that work.
When you publish allUsers
it will publish the user documents to Meteor.users
on the client - not to a collection called allUsers
. Also, I'm assuming askedByUsers
should return an array or a cursor of users and not just a single user. You can rewrite your helper like this:
Questions.helpers({
askedByUsers: function () {
return Meteor.users.find({ _id: { $in: this.askedBy } });
},
});
Then in a template you could do something like:
<template name='question'>
<ul>
{{#each askedByUsers}}
<li>{{name}}</li>
{{/each}}
</ul>
</template>
It's good that you applied a filter
to your allUsers
publisher. I'm going to assume users actually have a name
field, and it's not profile.name
or something else. Please correct your code as necessary.
Once you get this working, check out my answer to this question to explore how to publish a join (reactive or otherwise) so you can avoid publishing all of the users to the client.