Fred J.
Fred J.

Reputation: 6019

In method collection update not reactive on client template

The template helper .header in this Meteor code is expected to re render the "updated" value of the property headerLabel when the server method headerUpdate runs but it is failing to show the newly updated value even though the collection has been updated with the new value.

What is the correct way to fix this? Thanks

Template.header.helpers({
  headerLabel: function() {
    var userId = Meteor.userId();
    if (userId) {
      Meteor.call('getHeaderLabel', userId, function(err, res) {
        if (!err) {
          Session.set('headerLabel', res);
        }
      });
      return Session.get('headerLabel');
    } else {
      return 'Please login'
    }
  }
});

// on the client
Meteor.subscribe('headerLabelCol', Meteor.userId());

//on the server
Meteor.publish('headerLabelCol', function(userId) {
  return HeaderLabelCol.find({userId: userId}, {limit: 1});
});

// Meteor methods
getHeaderLabel: function(userId) {
  if (userId) {
    var result = HeaderLabelCol.findOne({userId: userId});
    if (result) { return result.headerLabel; }
  }
}

headerUpdate: function(userId, headerLabel) {
  HeaderLabelCol.update({userId: userId}, {$set: {headerLabel: headerLabel}});
}

edit
I changed the server size publish as below, using the reactive-publish package as below for no avail.

Meteor.publish('headerLabelCol', function (userId) {
  this.autorun(function (computation) {
   return HeaderLabelCol.find({userId: userId}, {limit: 1});
 });
});

Upvotes: 0

Views: 91

Answers (1)

Soubhik Mondal
Soubhik Mondal

Reputation: 2666

Two Solutions


Solution 1 - using Pub/Sub

  1. Publish headerLabelCol on server:

    Meteor.publish('headerLabelCol', function() {
        return HeaderLabelCol.find({
            userId: this.userId
        }, {
            limit: 1
        });
    });
  2. Subscribe to headerLabelCol on client:

    Meteor.subscribe('headerLabelCol');
  3. In your Template.header.helpers on client:

    Template.header.helpers({
        headerLabel: function() {
            var userId = Meteor.userId();
            if (userId) {
                var result = HeaderLabelCol.findOne({userId:userId});
                if(result) {
                    return result.headerLabel;
                } else {
                    return 'Not Found';
                }
            } else {
                return 'Please login';
            }
        }
    });

Note: you can update the Collection via Meteor.methods or Collection.allow.

Solution 2 - using Methods and Session

Your code works correctly when I tried it out. So I'm not sure what went wrong for you, here's how I would solve this problem:

Define the methods on both client and server.

  1. In your Meteor.methods on both client and server:

    Meteor.methods({
        getHeaderLabel: function(userId) {
            if (userId) {
                var result = HeaderLabelCol.findOne({
                    userId: userId
                });
                if (result) {
                    return result.headerLabel;
                } else {
                    return null;
                }
            }
        }, 
        headerUpdate: function(userId, headerLabel) {
            HeaderLabelCol.update({
                userId: userId
            }, {
               $set: {
                    headerLabel: headerLabel
               }
            });
        }
    }
  2. The Meteor.call:

    Meteor.call('getHeaderLabel', Meteor.userId(), function(err, res) {
        if (!err) {
            Session.set('headerLabel', res);
        }
    });
  3. You can call the above from either the Template.header.helpers (as you have done) or from within the Meteor.methods headerUpdate. Either will work, but I preferred to do it via headerUpdate, like this:

    headerUpdate: function(userId, headerLabel) {
        HeaderLabelCol.update({
            userId: userId
        }, {
            $set: {
                headerLabel: headerLabel 
           }
        });
        Meteor.call('getHeaderLabel', userId, function(err, res) {
            if (!err) {
                Session.set('headerLabel', res);
            }
        });
    }

This makes sure that the method is called every time the data is updated. So the Session, which is a reactive data source, is updated and the template helper is automatically called.

  1. The Template helper:

    Template.header.helpers({
        headerLabel: function() {
            if (Meteor.userId()) {
                return Session.get('headerLabel');
            } else {
                return 'Please login';
            }
        }
    });
  2. Initial call to getHeaderLabel Meteor method:

    Template.header.onCreated({
        Meteor.call('getHeaderLabel', Meteor.userId(), function(err, res) {
            if (!err) {
                Session.set('headerLabel', res);
            }
        });
    });

This will call the getHeaderLabel method initially, before the DOM is rendered.

Upvotes: 1

Related Questions