简体   繁体   中英

Meteor Routing, Pub/Sub

I'm trying to make a publishment statement to publish ONLY the author(OP)'s profile avatar. I am thinking of grabbing the _id of the page. And from that page, I will grab the userId which is the author's _id and try to show the profile.

However, I have been very unsuccessful, and currently, I am using the following. Publishing EVERY user's profile avatar.

Publications.js

//Need to filter this to show only OP.
Meteor.publish("userPostAvatar", function() {
    return Meteor.users.find( {} ,
    {
        fields: {'profile.avatar': 1}
    })
});

Meteor.publish('singlePost', function(id) {
  check(id, String);
  return Posts.find(id);
});


Router.js

Router.route('/posts/:_id', {
    name: 'postPage',
    waitOn: function() {
        return [
            Meteor.subscribe('singlePost', this.params._id),
            Meteor.subscribe('userStatus'), 
            Meteor.subscribe('userPostAvatar')
        ];
    },
    data: function() { 
        return Posts.findOne({_id:this.params._id});
     }
});

You can do a simple join in the userPostAvatar publish function like this:

Meteor.publish('userPostAvatar', function(postId) {
  check(postId, String);
  var post = Posts.findOne(postId);
  return Meteor.users.find(post.authorId, {fields: {profile: 1}});
});

This assumes posts have an authorId field - adjust as needed for your use case. Note three important things:

  • You will need to subscribe with this.params._id just as you did for singlePost .

  • The join is non-reactive. If the author changes, the avatar will not be republished. Given the general nature of posts I assume this isn't a problem.

  • I didn't publish the nested field profile.avatar on purpose because doing so can cause weird behavior on the client. See this question for more details.

I believe you can achieve this within the iron:router data context, by finding the post, associated author (whatever the field is), and then the subsequent user avatar. You can return an object to the iron:router data context. Then you can access post and avatar in the template as variables (so you might need to adjust the template output a little).

Publications.js

Meteor.publish("userPostAvatar", function() {
    return Meteor.users.findOne( {} ,
    {
        fields: {'profile.avatar': 1}
    })
});

Meteor.publish('singlePost', function(id) {
  check(id, String);
  return Posts.find(id);
});

Router.js

Router.route('/posts/:_id', {
    name: 'postPage',
    waitOn: function() {
        return [
            Meteor.subscribe('singlePost', this.params._id),
            Meteor.subscribe('userStatus'), 
            Meteor.subscribe('userPostAvatar')
        ];
    },
    data: function() {
        var post = Posts.findOne({_id: this.params._id});
        var avatar = Users.findOne(post.authorId).profile.avatar;
        return {
            post: post,
            avatar: avatar
        };
    }
});

Two problems with this method are that you could achieve the same thing with template helpers, and the user publication hasn't been limited to one user (I'm unsure how to do this unless we know the authorId within the waitOn, although maybe you could try moving the logic to there instead of the data context as my example shows).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM