简体   繁体   中英

No Reactive Update with Collection.find in Meteor

In a test app with collections Fruits and Meteor.users , a user clicks on the name of a fruit to add it to his favorite list, using server-side code

Meteor.users.update( Meteor.user()._id, { $push: {'profile.favorites': fruit_id } })

where fruit_id is the ObjectID fruit._id generated by Mongo.

For the favorite fruits page, the client also subscribes to a publication:

Meteor.publish('favoriteFruits', function() {

    return Fruits.find({
        '_id': {
            '$in' : Meteor.users.findOne(this.userId).profile.favorites
        }
    })

}

Problem: When a new fruit is made a favorite, nothing changes on the favorite fruits page unless a page refresh is made.

My guess is because in the publication code, the line containing $in is not reactive.

For this situation, what is the usual practice to enable the user to reactively see the newly added or removed fruits? Can Meteor.users.findOne(this.userId).profile.favorites be made reactive?


The subscription is done in the controller, I'm using Angular with Meteor.

angular.module('myApp').controller('FavoriteFruitsCtrl', function($scope, $meteor) {

    $meteor.autorun($scope, function() {

        $meteor
            .subscribe('favoriteFruits')
            .then(function() {
                $scope.favfruits = $meteor.collection(Fruits, false)
            })

    })

})

Based on the suggestions by @SylvainB and @Billybobbonnet, are we trying to do this? The second autorun containing .subscribe does re-run whenever there is changes to Meteor.user().profile.favorites !

angular.module('myApp').controller('FavoriteFruitsCtrl', function($scope, $meteor) {

    $meteor.autorun($scope, function() {
        Session.set('favorites', Meteor.user().profile.favorites)
    })

    // This autorun block will be triggered when the above autorun is triggered
    $meteor.autorun($scope, function() {
        var justForTriggering = Session.get('favorites')
        $meteor
            .subscribe('favoriteFruits')
            .then(function() {
                $scope.favfruits = $meteor.collection(Fruits, false)
            })
    })

})

However $meteor.subscribe function is not fired (by checking on the server side)

I would create a template level subscription using the array of favorite fruits as argument. It assumes that you exposes the profile.favorite field in another publication, but it should already be exposed by default for the current user.

Since you will wrap your subscription in an autorun and use a cursor from the users collection, the cahin of events will be as follows: updating profile > triggering autorun > updating publication of favorite fruits.

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