4

I am trying to use a Meteor.call function within a Handlebars block helper

Handlebars.registerHelper('get_handle', function(profileId, name) {
  Meteor.call("getProfileLink", profileId, function(error, result) {
    if (error) {
      return new Handlebars.SafeString('<a href="#">' + name + '</a>');
    } else {
      return new Handlebars.SafeString('<a href="http://twitter.com/' + result + '">' + name + '</a>');
    }
  });
});

I see in console.log(result) that the result is being returned, but the HTML from this helper is not being rendered. However, when I put the same Handlebars.SafeString return value out of the Meteor.call, it works fine. What am I doing wrong here? Or is it not correct to use a Meteor.call in the Handlebars block?

Prashant
  • 1,825
  • 1
  • 15
  • 18

1 Answers1

4

You can't use Meteor.call in a handlebars block with the paradigm above, primarily because of javascript's asynchronous design, by the time a value is received from the server, the return value has already been returned.

You can however pass it through using a Session variable:

Handlebars.registerHelper('get_handle', profileId, name,  function() {
    return new Handlebars.SafeString(Session.get("get_handle" + profileId + "_" + name));

});


//In a meteor.startup or a template.render
Meteor.call("getProfileLink", profileId, name, function(error, result) {
    if (error) {
       Session.set("get_handle" + profileId + "_" + name, '<a href="#">' + name + '</a>');
    } else {
       Session.set("get_handle" + profileId + "_" + name, '<a href="http://twitter.com/' + result + '">' + name + '</a>');
    }
});

Also be careful with trying to use have so many Meteor.call for each profileId and name (if you're using this in some sort of list or something) when you could request the data in one bulk request.

Hacky way

You can still do it the way you intend, but I would advise against it. I think its a bit inefficient.

Handlebars.registerHelper('get_handle', profileId, name,  function() {
    if(Session.get("get_handle" + profileId + "_" + name)) {
        return new Handlebars.SafeString(Session.get("get_handle" + profileId + "_" + name));
    }
    else
    {
        Meteor.call("getProfileLink", profileId, name, function(error, result) {
            if (error) {
                Session.set("get_handle" + profileId + "_" + name, '<a href="#">' + name + '</a>');
            } else {
                Session.set("get_handle" + profileId + "_" + name, '<a href="http://twitter.com/' + result + '">' + name + '</a>');
            }
        });
        return "Loading..."
     }
});
Tarang
  • 75,157
  • 39
  • 215
  • 276
  • Thank you Akshat. I thought I'd rather add this as a field to the document and retrieve, instead of rendering later. – Prashant Mar 03 '13 at 14:54
  • 1
    I've modified it and added a way for you to do that too – Tarang Mar 03 '13 at 14:57
  • I think the simplest way is to store the handle while creating a document and render it while retrieving the list. I didn't store the handle field before. But thanks anyway. I love hacks :) – Prashant Mar 03 '13 at 15:00