5

I need to inform clients about changes on server side. In my case I am using different Collections on server and on client (more about it in this question: how would you build pinterest like page with meteor.js).

On the server I am getting new Products from external API. I would like to publish the number of new items to all clients that they could update their local variables needed for layout to work well. How to do it?

It would be nice if I could publish/subscribe other kinds of data than Meteor.Collection. I found Meteor.deps, but what I understand it works only on client side.

Community
  • 1
  • 1
krzysu
  • 402
  • 4
  • 9

2 Answers2

2

To accomplish what you want you do need another collection - on the client. On the server, in a publish function, build a document from scratch assigning the current count of Products to an attribute. Using observe() and set, modify count when documents are added or removed from Products. Subscribe to the count "record set" on the client.

// Server
Meteor.publish('count', function () {
    // Build a document from scratch
    var self = this;
    var uuid = Meteor.uuid();
    var count = Products.find().count();
    // Assign initial Products count to document attribute
    self.set('count', uuid, {count: count});

    // Observe Products for additions and removals
    var handle = Products.find().observe({
        added: function (doc, idx) {
            count++;
            self.set('counts', uuid, {count: count});
            self.flush();
        },
        removed: function (doc, idx) {
            count--;
            self.set('counts', uuid, {count: count});
            self.flush();
        }
    });
    self.complete();
    self.flush();
    self.onStop(function () {
        handle.stop();
    });
});

// Client
Counts = new Meteor.Collection('count');
Meteor.subscribe('count');
console.log('Count: ' + Counts.findOne().count);
ram1
  • 6,290
  • 8
  • 41
  • 46
  • 1
    Very nice trick - I would also recommend looking at eventedmind tutorial on the ddp protocol which gives some basics to understand what's going on: http://www.eventedmind.com/posts/meteor-subscriptions-and-ddp – sarfata Feb 12 '13 at 22:49
0

I must say the above solution showed me one way, but still, what if I need to publish to client data that are not connected with observe()? Or with any collection?

In my case I have i.e. 1000 products. To engage visitors I am "refreshig" the collection by updating the timestamp of random number of products, and displaying collection sorted by timestamp. Thank to this visitors have impression that something is happening.

My refresh method returns number of products (it is random). I need to pass that number to all clients. I did it, but using (I think) ugly workaround.

My refresh method sets Session.set('lastRandomNo', random). BTW: I didn't know that Session works on server side. refresh updates Products collection.

Then accoriding to above answer:

Meteor.publish 'refreshedProducts', ->

self = this
uuid = Meteor.uuid()

# create a new collection to pass ProductsMeta data
self.set('products_meta', uuid, { refreshedNo: 0 })

handle = Products.find().observe
  changed: (newDocument, atIndex, oldDocument) ->
    self.set('products_meta', uuid, { refreshedNo: Session.get('lastRandomNo') })
    self.flush()

self.complete()
self.flush()
self.onStop ->
  handle.stop()

and on client side:

ProductsMeta = new Meteor.Collection('products_meta')

# subscribe to server 'products_meta' collection that is generated by server
Meteor.subscribe('refreshedProducts')

ProductsMeta.find({}).observe
  changed: (newDocument, atIndex, oldDocument) ->

    # I have access to refreshedNo by
    console.log ProductsMeta.findOne().refreshedNo

What do you think?

krzysu
  • 402
  • 4
  • 9