bartezr
bartezr

Reputation: 789

Meteor Template helpers: {{keyname}} showing blank

comment.html:

<template name="comment">
    <img src="{{photo}}"> //blank
    {{photo}} //blank
</template>

comments.js:

Template.comment.helpers({
    photo: function(){
        Meteor.call('getPhoto', function(error, result) {console.log(result);return result})
    }
});

server.js:

Meteor.methods({
    getPhoto: function () {
        return Meteor.user().services.vk.photo;
        }
});

Problem: console.log returns right value, but {{photo}} is empty. Question: why 'photo' is empty?

Upvotes: 1

Views: 193

Answers (1)

Archy Will He
Archy Will He

Reputation: 9767

[update]

I just realized what's the problem here.

Meteor.call is calling an async function, like an ajax call. So Meteor.call('getPhoto') would return undefined, the result is only retrievable in the callback

Meteor.call('getPhoto',function(err,result){console.log(result)});

With that in mind, you would need to come up with a way that captures that result in the callback. One solution is to use ReactiveVariable:

You would first need to $ meteor add reactive-var

Template.comment.created = function (){
    var $this = this;
    $this.photo = new ReactiveVar("loading");
    Meteor.call('getPhoto', function (err, result) {
        if (err) console.log(err);
        $this.photo.set(result);
    });
}

And now define your helper to get the value;

   //this is optional
   Template.comment.helpers({
        photo: function(){ 
           return Template.instance().photo.get();
        }
    });

Another solution is to use Session:

  //everything here is in the client
  Meteor.call('getPhoto', function(error, result){
    Session.set('thePhoto', result);
  });

  // use reactive Session variable in helper
  Template.comment.helpers({
    photo: function(){
      return Session.get('thePhoto');
    }
  });

The thing about using Session is that you are setting a global variable and if you have many comments and every comment would need to have an unique photo, Session is probably not the best way to do it.


You are calling the function Meteor.call when you are declaring the helpers.

Template.comment.helpers({
    photo: Meteor.call('getPhoto', function(error, result) {console.log(result);return result})

});

So what you are doing is equivalnt to:

var a = Meteor.call('getPhoto', function(error, result) {console.log(result);return result})
Template.comment.helpers({
        photo: a //a is just a value 
});

For .helpers to work properly, you should be assigning a function to photo instead.

Template.comment.helpers({
    photo: function(){
       var r;
       Meteor.call('getPhoto', function(error, result) {r = result});
       return r;
    } 
});

Under the hood, each helper starts a new Tracker.autorun. When its reactive dependencies change, the helper is rerun. Helpers depend on their data context, passed arguments and other reactive data sources accessed during execution. -From Meteor Doc

.helpers is supposed to be invoked as the very reason why you want to use .helpers is to enable reactivity in your view. Thus what's inside .helpers need to be functions.


If you still don't get what I mean, here is simplified example:

var a = function(){ console.log("hey"); return 1}

var b = a();

var c = a; 

b(); //this would run into an error saying that b is a not a function

c(); //this would console.log "hey"

Upvotes: 2

Related Questions