Why is this subscription not reactive?

Hey all,

I’m trying to implement a feature where the client may select how to sort a list returned by a publication. In my case, switching between “top posts” and “most recent” posts. The way I’m doing it is to set a ReactiveVar inside the “user_posts” template, and toggle it on clicking a DOM element. The following code is inside the template’s onCreated function:

Template.user_posts.onCreated(function userPostsOnCreated() {
    this.subOptions = new ReactiveVar({sort: {createdAt: -1}, limit: 15});  // 'new posts'
    this.toggleSortText = new ReactiveVar('top');

    this.autorun(() => {
        this.subscribe('userPosts.user', this.getUsername(), this.subOptions.get());
    });
});

Then I have the following event:

Template.user_posts_all.events({
    'click .toggle-posts-sort': function(e) {
        e.preventDefault();

        const currSortText = Template.instance().toggleSortText.get();
        if (currSortText == 'top') {
            Template.instance().subOptions.set({sort: {upvotes: -1, createdAt: -1}, limit: 15});
            Template.instance().toggleSortText.set('new');
        }
        else if (currSortText == 'new') {
            Template.instance().subOptions.set({sort: {createdAt: -1}, limit: 15});
            Template.instance().toggleSortText.set('top');
        }
    },
});

This event toggles the text contained in the .toggle-posts-sort class just fine (it’s just a <span> element in my template). console.logging the two ReactiveVars inside the this.autorun(() => { block indicates that the sort parameter of subOptions is changing appropriately to include or not include “upvotes” whenever the event is triggered. However, nothing from the subscription changes when clicking .toggle-posts-sort (i.e. the posts don’t re-order themselves).

The guide seems to suggest that a pattern like this should work, so I’m not exactly sure where I’m going wrong. Any ideas?

A quick update, I cleaned up the structure a bit so that “top” posts and “new” posts are accessible at /:username/posts/top and /:username/posts/new respectively. These routes load the same template but have different names inside of FlowRouter, and I check for the current route with FlowRouter.getRouteName() inside this.autorun. When I refresh the page on the .../top route, the posts indeed get sorted according to the number of “upvotes” that they have, and likewise according to the date they were posted on the .../new route.

So the actual sorting in the subscription works, and I don’t know why this isn’t updating as soon as the ReactiveVar changes.

Are you using the updated sort criteria in your find statement (on the client)?

Hi @hluz, no, I’m just calling return UserPosts.find({}); from a helper method and iterating over that cursor in the template.

EDIT: I just tried doing this, changing the sort parameter when I call find from the client, but there was no change of behavior (the page still needs to be refreshed to see the new sort order take effect).

Right… The Subscription only selects the data that will be pushed to the client and added to your cache collection (in minimongo). That part, if I understand you correctly, is working fine. Now, you have the data in your client, so how you retrieve it is up to the find statement in your helper… you should use the appropriate search condition, including the sort criteria. This is needed also because the client side collection may contain data from more than one subscription (i.e., don’t assume that all there is in minimongo is what you subscribed in ‘userPosts.user’).

1 Like