Arlo Feirman
Arlo Feirman

Reputation: 95

Why Don't I have 'this' context inside of a .then() in my Ember component

I'm fairly new to Ember.

This is the code for my component:

import Ember from 'ember';

export default Ember.Component.extend({
  profiles: Ember.inject.service(),
  tagName: 'td',
  classNames: ['grey'],
  classNameBindings: ['unreadMessages'],
  unreadMessages: null,

onInit: function() {
    const id = this.get('conversation.id');
    return this.get('profiles').getMessages(id)
      .then(function(bool) {
        this.set('unreadMessage', bool);
      });
  }.on('init')
});

This throws:

TypeError: Cannot read property 'set' of undefined

So I can gather that I don't have the this context that I need to call this.set inside of the .then()

I need to assign the result of return this.get('profiles').getMessages(id) to the unreadMessages property in my component. So that I can use it for the classNameBinding.

Here is the method I'm calling from the service

  getMessages(id){
    return this.get('ajax').request('/messages?id=' + id)
    .then((obj) => {
      const unreadMessages = obj.messages.filter((e) => e.read === false);

      if (unreadMessages === []) {
         return false;
      } else {
         return true;
      }
    });
  }

I've only been able to access the boolean value that getMessages returns inside of its .then() and I am not able to call this.set() inside of the .then() I'm looking for a work around. I think I'm close and am struggling to due to my lack of experience with Ember.

getMessages makes a 'GET' request to my back end and filters through the messages to check if there are any that are unread and then returns true or false. The purpose of the classNameBinding is to notify the user of whether they have any unread messages for that thread. This is a very simple email style messaging app that I am building for practice.

Thanks!

Upvotes: 0

Views: 162

Answers (1)

Surya Purohit
Surya Purohit

Reputation: 1120

Change

onInit: function() {
    const id = this.get('conversation.id');
    return this.get('profiles').getMessages(id)
      .then(function(bool) {
        this.set('unreadMessage', bool);
      });
  }.on('init')
});

to

onInit: function() {
    const id = this.get('conversation.id');
    return this.get('profiles').getMessages(id)
      .then((bool) => {
        this.set('unreadMessage', bool);
      });
  }.on('init')
});

The thing here is, the scope changes when you write function(){} inside then and this won't refer to the component this. That's why in ES6 the concept of lexical this was introduced. This will retain the this. So use Arrow function instead and it'll work smoothly..

Upvotes: 2

Related Questions