Search code examples
javascriptmeteorecmascript-6meteor-blaze

Meteor - Arrow Functions breaking #each loop in ES6


I'm hoping I got the right area to ask for this... Below is some code from two files I'm working on. When I change anything with 'this.' in the function to an arrow function, the code no longer functions as expected.

Is someone able to explain what I'm doing wrong? Do I need to do something differently when using arrow functions? Am I using 'this.' incorrectly to begin with? Should I not be using arrow functions in this way?

Help is greatly appreciated.

client/views/jobList.html

{{#each jobs}}
    <tr>
        <td>{{jobID}}</td>
            <td>{{user.fullname}}</td>
            <td>{{product.type}}</td>
            <td>{{shortDesc}}</td>
            <td>{{formattedDate}}</td>
            <td>{{phone}}</td>
            <td>{{user.username}}</td>
            <td>{{jobType}}</td>
            <td>{{product.brand}}</td>
            <td>{{product.type}}</td>
            <td>{{product.model}}</td>
        </tr>
    {{/each}}

client/views/jobList.js

Template.jobList.helpers({
    jobs: ()=> Jobs.find({}, {sort: {jobDate: 1}}),

    formattedDate: function() { // Changing this to arrow function breaks functionality
        let d = this.jobDate;
        let e = formatDate(d);
        return e;
    },
    shortDesc: function () { // Changing this to arrow function breaks functionality
        if (this.description.length > 40) {
            return this.description.substr(0, 50) + '...';
        } else {
            return this.description
        }
    },
    jobID: function () { // Changing this to arrow function breaks functionality
        let a = this.jobNum;
        let e = this.jobType.substr(0, 1);
        return e + a
    }
});

Solution

  • One of the fundamental things about arrow functions is that they inherit (close over) the this in the context in which they're created. Your code relies on this being set by the way the function is called, so arrow functions aren't a good choice there.

    Here's an illustration of the difference and the problem:

    var obj = {
        foo: () => {
            console.log("foo: this.prop:", this.prop);
        },
        bar: function() {
            console.log("bar: this.prop:", this.prop);
        },
        prop: "the property"
    };
    obj.foo(); // Doesn't show `prop` because `this` != `obj`
    obj.bar(); // Does show `prop` because `this` == `obj`