2

I have two collections items and worksheet.

Each worksheet has an item array field where I store all the worksheet items _id. Based on this field, I publish items for the current worksheet. The publication looks like that:

 Meteor.publish("get_items", function(worksheetId) {
    var currentWorksheet = Worksheets.findOne(worksheetId); 
        if (currentWorksheet.items) {
            return Items.find({"_id":{$in:currentWorksheet.items}}, {});
        } else {
            console.log("no item to send");
            return Items.find({"_id":null}, {});
        }
    }
    return this.ready();
});

This publication is subscribed in the current page iron-router controller.

Here is the problem:

I use a dedicated component with a template level subscription in order to change the current worksheet items field. This component is loaded in a bootbox.

When I change the current worksheet items field, my main publication does not update to take the changes into account. However, if I reload the page, the changes are taken into account.

How should I design my publication so that it stays reactive despite having a dependency on another collection?

Billybobbonnet
  • 3,156
  • 4
  • 23
  • 49

1 Answers1

2

You can use Meteor.publishComposite() as follows

Meteor.publishComposite('itemsByWorksheet', function (params) {
    check(params, {
        worksheetId: String
    });

    var worksheetId = params.worksheetId;
    return {
        find: function () {
            return Worksheets.find({ worksheetId: worksheetId })
        },
        children: [
            {
                find: function (worksheet) {
                    return Items.find({_id: {$in: worksheet.items}})
                }
            }
        ]
    }
});

This will create a reactive publication that will subscribe to items based on the changes in the original worksheet publication.

You will need the following package from atmosphere for this solution: https://atmospherejs.com/reywood/publish-composite

Your subscription would look like this:

Meteor.subscribe('itemsByWorksheet', {worksheetId: "<worksheet id goes here>"});
challett
  • 906
  • 6
  • 16
  • Thank you for your input, this answers my question. However, it must be noted that this approach uses a `Cursor.observe()` with all the performance and scalability issues attached. I finally achieved the same result from client by re-subscribing (items id list as arg) each time my worksheet item change. – Billybobbonnet Sep 16 '15 at 08:33