[solved] Collection helpers with template based subscriptions


#1

I like the dburles:collection-helpers package to add structure to collections
however when using template based subscriptions, collection helper functions are getting triggered before the entire subscription is ready , leading to exceptions.

How can I avoid this and run collection helpers when all subscriptions are ready ?

I am also using reywood:publish-composite could that be a reason for missing data when collection helpers run ?

Regards
Sach!n


#2

Hi, try this :

Inside the template’s HTML, you can use the built-in helper Template.subscriptionsReady, which is an easy pattern for showing loading indicators in your templates when they depend on data loaded from subscriptions.
http://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe


#3

Hi

Maybe my question was not very clear.
The issue is not with Template Helpers
But Collection helpers as enabled with dburles:collection-helpers package. this helpers do not belong to any specific templates.


#4

What are the exceptions you see on your console?

Also, can you post your publication as well as template (html,js) code, perhaps there is something you are missing.

I’ve been successfully using collection helpers and publish composite with template subscriptions for a long time now. Have not had a problem so far.


#5

Hi

Here’s my publication code

Meteor.publishComposite('homePageSub', {
  find: function(){
    return ParentCol.find( {}, {fields: {title: 1, image:1, domain:1}, limit: 60});
  },
  children: [
    {
    find: function(parent){
          return ChildCol.find({domain: parent.domain},{fields:{domain:1,title:1,image:1,slug:1}});
          }
    }]
});

and here the collection helper :

ParentCol.helpers({
  relatedChild : function (){
    return ChildCol.findOne({domain: this.domain},{fields: {title:1,image:1,slug:1}});
  },
  childPage : function (){
    var childObj = ChildCol.findOne({domain: this.domain},{fields: {slug:1}});
    return FlowRouter.path('childPage', {slug: childObj.slug});   // line with error 
  }

The error I get is

Exception in queued task: TypeError: Cannot read property ‘slug’ of undefined

for object ChildObj in the line marked with comment above


#6

Since data is reactive and it is not always available on the client (before the subscriptions are ready at least) you should use protective property checks in your javascript. In your case, since childObj is not always there, childObj.slug is therefore not always an existing property, therefore is sometimes undefined. Here’s what you could do:

ParentCol.helpers({
  relatedChild : function (){
    return ChildCol.findOne({domain: this.domain},{fields: {title:1,image:1,slug:1}});
  },
  childPage : function (){
    var childObj = ChildCol.findOne({domain: this.domain},{fields: {slug:1}});
    // First check if we actually have a childObj
    return childObj && FlowRouter.path('childPage', {slug: childObj.slug}); 
  }

#7

thanks @serkandurusoy, it worked like a charm.

However, it makes me think if using subscription in the route is better option when using publishComposite with hierarchies?


#8

Why would you think that?

Publish composite is just a utility that lets you publish from multiple collections.

Subscribe is a mechanism where you connect to a publication for the data you need.

Where you need the data is irrelevant of router/template disinction.

On the contrary, it is still a very good idea to keep the subscriptionin the template, where the data is actually used.

I’ve been using publish composite, collection hooks, collection helpers, collection2, simple schema together extensively and it fits very naturally with template subscription.