Accessing to Template.instance() in Meteor.method callbacks

Hi,
Is it possible to get access to a Template.instance() within a Meteor.method callback?
Something like this:

Meteor.call(“locationByCoordinates”, e.latlng, function (err, result) {
Template.instance().location.set(result[0]);
});

Now Template.instance() returns null if it is called from callback.

Pass it in as a param to the call

You should also be able too

const temp = Template.instance()

Meteor.call('foo', (error, bar) => {
    if(error)
        return //handle error
    temp.bar = bar
})

with a lexical scoped callback function (like in the above example), calling the instance like you originally did should work too :slight_smile:

Yes. I did it on this manner. Hm-m, it seems not meteor way, isn’t it?

I’m not sure I understand what you mean :slight_smile: isn’t it almost exactly the same as what you had before?

It’s the ES6 way, which makes it the Meteor way too, IMO :wink:

There is no special Meteor way to accomplish what you’re looking for.

Explanation:

Template.instance() works when the code that you’re currently executing is running within the context of a template render / rerender / create / destroy. In any other context it doesn’t make sense to ask Meteor what the currently executing template is, because there is none.
So the way to get a reference to a specific template that is not currently executing could be to simply save it in a variable for later use, as the other posters in this thread have suggested.

Technically it would be possible for Meteor to remember that you’ve used the Meteor.call method with callback from within a context that was executing a template, and so Template.instance() could be made to remember that and give you back that template instance inside the callback, but there are reasons why this wouldn’t be a very good idea. There would likely be unnecessary overhead introduced, plus the semantics of “which template is currently executing” would be stretched, which could lead to unexpected behavior. Though, I’m not entirely sure that it would be a bad idea or that it would be hard or costly to implement.

Maybe you could add some more context as to what problem you’re solving and how you’re implementing your solution (beyond the method call). That could maybe give me an opportunity to guide you in terms of a “Meteor way” to solve your problem :sunny:

O-o, my context is the following: the app gets GPS data on the device and calls server methods for geocoding. The result of geocoding app puts to template reactive variable.

Now I use the next:

Template.customer.onRendered(function () {
    var template = Template.instance();
    map.on('contextmenu', function (e) {
        Meteor.call("locationByCoordinates", e.latlng, function (err, result) {
            template.location.set(result[0]);
        });
    });
});

@seeekr, Thanks for detailed explanation!

Write ()=>{...} instead of function(){...}. Then you can reference the instance using this at any depth of your callback chain.

@goatic sorry, I haven’t good understanding coffeescript. I have believed constructions like ()=>{...} are transpiled to function(){}. Am I wrong?

I don’t know or use coffescript. This is pure JavaScript. It’s called an arrow/lambda/lexical function :slight_smile: it’s a new way to do functions that was made exactly for the problem you’re asking about

Yes, they are transpiled to something like that. The key difference is that the arrow function (or closure) syntax also binds the this reference to what it was in the outer scope.

Example:

Template.foo.onRendered(function () {
  this.i = 1
  Meteor.call('bar', () => {
    // the `this` in here is still the previous `this`
    console.log(this.i) // outputs: 1
  })
  // for comparison without arrow function syntax:
  var self = this
  Meteor.call('bar', function() {
    console.log(this.i) // outputs: undefined
    console.log(self.i) // this works, outputs: 1
  })
})

(What () => {} is transpiled to is roughly (function() {}).bind(this).)

And while this syntax also exists in CoffeeScript, it is also part of the ES6/ES2015 standard and can be used in Meteor with either some babel package or the new ecmascript package.

1 Like