I'm trying to display the number of users in my footer and I would like this number in real time. I think the proper way is to create a publication in the server and to subscribe from the client.
// server/publications.js
Meteor.publish("usersCount", function () {
return Meteor.users.find();
});
// client/main.js
UsersCount = new Meteor.Collection("usersCount");
Meteor.subscribe('usersCount', [], function() {
console.log('subscribed.');
});
// client/views/layout/footer.js
Template.footer.helpers({
famecoiners: function(){
return UsersCount.find().count();
}
});
// client/views/layout/footer.html
<span>{{famecoiners}} Famecoiners!</span>
In the chrome console, we can see the 'subscribed' string from the callback function. The problem is: {{famecoiners}} always returns 0 in my template.
If the client passed arguments to subscribe , the function is called with the same arguments. To publish records to clients, call Meteor. publish on the server with two parameters: the name of the record set, and a publish function that Meteor will call each time a client subscribes to the name.
In Meteor a publication is a named API on the server that constructs a set of data to send to a client. A client initiates a subscription which connects to a publication, and receives that data.
Publishing all of the users will work, but it isn't practical. What if you have 10,000 users? What you really want to do is create a client side collection that holds only one item representing the count. If you look at the second example in the Publish and subscribe section of the docs, you'll see something that does this. I'll present a complete working example below:
$ meteor create test
$ cd test
$ rm test.*
$ mkdir server client
$ meteor remove autopublish
$ meteor add coffeescript
# Create a client-side subscription for the count of users.
UsersCount = new Meteor.Collection 'users-count'
Meteor.subscribe 'usersCount'
Meteor.startup ->
Meteor.setInterval (->
# To show something working, read the users count every second.
uc = UsersCount.findOne()
console.log uc.count or 0
), 1000
# Create a 'Users' group for this demo instead of using accounts-password.
Users = new Meteor.Collection 'users'
Meteor.publish 'usersCount', ->
count = 0 # the count of all users
initializing = true # true only when we first start
handle = Users.find().observeChanges
added: =>
count++ # Increment the count when users are added.
@changed 'users-count', 1, {count} unless initializing
removed: =>
count-- # Decrement the count when users are removed.
@changed 'users-count', 1, {count}
initializing = false
# Call added now that we are done initializing. Use the id of 1 since
# there is only ever one object in the collection.
@added 'users-count', 1, {count}
# Let the client know that the subscription is ready.
@ready()
# Stop the handle when the user disconnects or stops the subscription.
# This is really important or you will get a memory leak.
@onStop ->
handle.stop()
Meteor.startup ->
# To show something working, insert a new user ever 0.5 seconds.
Meteor.setInterval (-> Users.insert {}), 500
Sorry if you don't like the CoffeeScript - I wanted the code to be compact.
$ meteor start
If you open the console you will see the user count increase. For fun you can open the mongo shell and run db.users.remove();
and watch it reset.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With