Meteor helper doesn't work on template as expected

I have the following code in my template’s helper:

Template.ListPosts.helpers({
	drawingPosts: () => {
		return Drawings.find({});
	},
	userVoted: () => {
		if(Drawings.find({_id: this._id, votedUsers: {$in: [Meteor.userId()]}}).count() == 1) {
			return true;
		} else {
			return false;
		}
	}
})

I can access the drawingPosts in the helper with no issues, but when I try to use userVoted as follows:

{{#if userVoted}}
	<i id="heart" class="fa fa-heart" aria-hidden="true" style="font-size: 18px; position: relative; left: 110px; color: red"></i>
{{else}}
	<i id="heart" class="fa fa-heart-o" aria-hidden="true" style="font-size: 18px; position: relative; left: 110px"></i>
{{/if}}

the script inside {{else}} get executed even when I console.log(Drawings.find({_id: this._id, votedUsers: {$in: [Meteor.userId()]}}).count()) I get 1, but inside the template, userVoted seems to be always false

What am I doing wrong here?

The issue is that you are using this inside an arrow function here:

Arrow functions take the context from the place it’s declared in code and the context can’t be changed when run.
In this case, the helpers declaration is top level for the module, so this refers to global.

Meteor runs helpers with the current data as the context, but when you use an arrow function, it can’t change the context, and so this doesn’t point to the current data (which has the _id).

The solution is to use a regular function:

	userVoted() {
		if(Drawings.find({_id: this._id, votedUsers: {$in: [Meteor.userId()]}}).count() == 1) {
			return true;
		} else {
			return false;
		}
	}
2 Likes

Thank you for the extensive detailed explanation, appreciate your help :pray: