TL77
TL77

Reputation: 83

Meteor data context within templates vs helpers

Trying to understand better how data contexts works in Meteor, as I can't figure out this problem I'm facing. Haven't found a clear answer anywhere. I have the following templates

<template name="list">
  {{#each listItem}}
    {{> listItemDetail}}
  {{/each}}
</template>

<template name="listItemDetail">
  <p>{{_id}} {{title}}</p>
  <p>{{idViaHelper}}</p>
</template>

And in my Javascript I have

Template.list.helpers({
    'listItem': () => {
        return List.find().fetch();
})

Template.listItemDetail.helpers({
    'idViaHelper': () => {
        return this._id
})

As far as my understanding of data contexts within Meteor goes, using #each sets the context for each instance of the listItemDetail template to be a document that that is returned from the listItem helper.

And this works as I'd expect when it comes to using {{_id}} in the listItemDetail template, showing the ID of the document.

But if I try to get the same _id via a helper {{idViaHelper}} which uses this._id, I get undefined. When I try console.log(this), it shows me that this is referring to the Window object. But I have no idea why. What is going on and why does the data context not get picked up in the template helper?

This is my first post, thanks for your help!

Upvotes: 0

Views: 112

Answers (2)

Micah Henning
Micah Henning

Reputation: 2185

Julien Leray is correct in his answer regarding lexical this. You lose the data context when using lambda expressions. However, Meteor offers you ways to access your Template data without lexical this, viz.:

Template.list.helpers({
  'listItem': () => List.find().fetch();
});

Template.listItemDetail.helpers({
  'idViaHelper': () => Template.currentData()._id
});

You can use both Template.currentData() and Template.instance().data.

Also, note that if you have a lambda expression that only includes a single return statement, you can use the shortcut syntax as I did above.

// ECMAScript 5
var myFunc = function (a, b, c) {
  return b * a - c;
};

Becomes:

// ECMAScript 6
const myFunc = (a, b, c) => b * a - c;

Upvotes: 0

Julien Leray
Julien Leray

Reputation: 1687

You are right about the Meteor datacontext flow. What you are doing is working.

You only forget what the this represent into a lambda function.

Read the the part Lexical this from MDN, it's better explained than what I could say: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

For your case, the easier way to get the datacontext directly from your this on helpers is to pass by usual anonymous function.

Just try:

Template.listItemDetail.helpers({
    'idViaHelper': function(){
        return this._id
})

That's it.

You've got unlucky on this one, there is no issue related to Meteor here.

Other related question you could find useful: meteor helper functions, lambdas and lexical this

Upvotes: 1

Related Questions