Reputation: 1449
I have a Meteor method that returns all user accounts on my application
returnUsers: function(){
return Meteor.users.find().fetch();
}
I'm using new ReactiveVar
to pass the return value of the Meteor method into my template helper:
Template.listViewTemplate.created = function (){
var self = this;
self.myAsyncValue = new ReactiveVar("Waiting for response from serv er...");
Meteor.call('returnUsers', function (err, users) {
if (err)
console.log(err);
else
self.myAsyncValue.set(users);
});
}
Template.listViewTemplate.helpers({
userCollection: function(){
return Template.instance().myAsyncValue.get();
}
});
But when I go to render the users into the view, I get a console error that reads
{{#each}} currently only accepts arrays
When I render without the #each
iterator, using
<ul id='usersList'>
{{userCollection}}
</ul>
the output on my web-page accurately reflects the number of users (2), but reads
[object Object],[object Object]
I'm pretty sure that there is some funkiness going on here because I'm using a global Meteor collection (Meteor.users.find().fetch()
, as opposed to having defined my own collection), but I'm not sure how to get around it.
I want to display a list of all users so the current user can click another user and share a document with them--not sure how to get around this.
Upvotes: 1
Views: 3828
Reputation: 3360
ReactiveVar doesn't like arrays. You could install the ReactiveArray package which should accomplish exactly what you want.
Based on comment of mper
In the latest versions of Meteor you can put an array in a ReactiveVar.
Tested on
Upvotes: 2
Reputation: 301
I have several remarks about your question:
You don't need .fetch()
on your method. When you call find()
on collections, such as Meteor.users
a cursor is returned. The template (and #each
in particular) can iterate through cursors. Cursors are usually better because you don't load the entire collection into memory at once - fetch
does.
Meteor collections are already reactive, meaning that if they change, they will trigger changes on your templates as well. So, you don't need to use a ReactiveVar
to wrap your collection.
You don't need to use a method to get the users and in fact, you shouldn't, because usually you want to make queries to the database stored locally, not make calls to the server. Just call Meteor.users.find()
directly in your template helper. You can (and should) control what is available locally through subscriptions.
#each
with else
You can use the following in your template:
{{#each userCollection}}
...
{{else}}
Waiting for response from server...
{{/each}}
If userCollection
is empty, the template will render the else
block, just like you wanted.
Delete your method and onCreated
with everything inside, change whatever is inside your template helper to only return Meteor.users.find()
and use {{#each userCollection}}...{{else}}Waiting for response from server...{{/else}}
In the latest versions of Meteor you can put an array in a ReactiveVar
.
Upvotes: 1
Reputation: 21
Template.onCreated(function(){})
only gets run once and meteor methods only run once
You need reactivity here.
Collections sre reactive meaning pub/sub
.
You need to create a publish function
that allows certain users to fetch other users in the database. So all uses with maybe if the currentUser has permission to read all user info. Id limit the fields too.
Upvotes: -1
Reputation: 1612
You don't need to use a reactive variable for this. The function at Template.listViewTemplate.created
is not container in an autorun, which means: It won't get recomputed.
The best approach for your scenario is: Use a variable to get the status ( loading, loaded, error) and another variable to save the array itself attach to self. Reactivity is cool but you should only use it when needed.
About:
[object Object],[object Object]
This is happening because you're not extracting any value form the object provided nor looping using {{#each}}.
Your solutions for listing users is dangerous and inefficient. You're sending to the client all the fields from the user collection, including login tokens.
The best approach is to create a subscription that send only the necessaries fields like: _id, info.firstName. You should also have some criteria to the list users and use pagination. Consider also a search feature for such purpose.
Upvotes: 2