meteormeteor-blazemeteor-publications

Meteor, publish:composite. how to access joined data in the template?


So I used publishComposite to do a collection join in Meteor. I have a parent collection (Subscriptions) with a user_id foreign key. I look up the user name in the Meteor.users collection to get the actual username, but how do I actually print this in the html template. My subscription data is there but how do I actually refer to the username?

Here is the publish code:

//publish subscriptions course view
Meteor.publishComposite('adminCourseSubscriptions', function(courseId){
  return {
    //get the subs for the selected course
    find: function(){
        return Subscriptions.find(
            {course_id: courseId}
        );
    },

    children: 
    [
        {   
            //get the subscriber details for the course
            find: function(sub){
                return Meteor.users.find({_id:sub.user_id});
            }

        }

    ]
  };

});

here are the template subdcriptions:

Template.adminCourseDetail.helpers({
  courseDetail: function(id){
    var id = FlowRouter.getParam('id');
    return Courses.findOne({ _id: id });
  },
  courseSubscriptions: function(){
    var id = FlowRouter.getParam('id');
    return Subscriptions.find({course_id:id})
  },
  users: function(){
    return Meteor.users.find();
  }
});

and the template (which is garbage) ps the course details come from a separate collection. It was easier and I think more performant to get the details separately and this works fine. It's just the username that I cannot display correctly:

<template name="adminCourseDetail">
<h1>Course Details</h1>
<p>Title: {{courseDetail.title}}</p>
<p>Description: {{courseDetail.description}}</p>
<p>Start Date: {{courseDetail.startDate}}</p>
<p>Number of sessions: {{courseDetail.sessions}}</p>
<p>Duration: {{courseDetail.duration}}</p>
<p>Price: {{courseDetail.price}}</p>
<p>{{userTest}}</p>
<a href="#">edit</a>
<a href="#">delete</a>
<h2>Course Subscriptions</h2>
{{#each courseSubscriptions}}
    <div class="row">
        <div class="col-md-3">{{username}}</div>
        <div class="col-md-3">{{sub_date}}</div>
    </div>
{{/each}}
</template>

Thanks in advance for any suggestions!


Solution

  • As far as I understand your question, documents of the Subscriptions collection contain only the attribute user_id, referencing the corresponding user document in the Meteor.users collection. If this is the case, then you need to add an additional template helper which returns the username:

    Template.adminCourseDetail.helpers({
      // ...
      getUsername: function() {
          if (this.user_id) {
            let user = Meteor.users.find({
              _id: this.user_id
            });
            return user && user.username;
          }
          return "Anonymous";
        }
      // ...
    });
    

    After that, just replace {{username}} with {{getUsername}}:

    <template name="adminCourseDetail">
       <!-- ... -->
       <h2>Course Subscriptions</h2>
       {{#each courseSubscriptions}}
          <div class="row">
             <div class="col-md-3">{{getUsername}}</div>
             <div class="col-md-3">{{sub_date}}</div>
          </div>
       {{/each}}
       <!-- ... -->
    </template>
    

    Probably you misunderstood the concept of the reywood:publish-composite package. Using Meteor.publishComposite(...) will just publish a reactive join, but it will not return a new set of joined data.