5

Not sure what I'm missing here.

I need to get the output of data into this.contact. Right now, I'm using a static class variable, but it seems dirty to have to do that.

export class contactEdit {
  static t; // static class var
  constructor() {
    this.id = null;
    this.contact = null;
    contactEdit.t = this;
  }

  activate(id) {
    this.id = id;
    let contact = this.contact; // scoped version of class var
    return dpd.contacts.get(id).then(function(data) {
      console.log(data);
      contactEdit.t.contact = data; // this works
      contact = data; // this doesn't
    });
  }
}

Normally I would create a var contact inside the activate() function (it works in the Chrome console) but this doesn't seem to working in ES6.

Chrome console:

var c = null;
undefined
c;
null
dpd.contacts.get('a415fdc8f5a7184d').then(function(data) {
      c = data;
    });
Object {}fail: (n)then: (e,t)__proto__: Object
c;
Object {firstName: "John", lastName: "Doe", id: "a415fdc8f5a7184d"}
Andrew Grothe
  • 2,562
  • 1
  • 32
  • 48
  • 1
    Did you not just want `this.contact = data;` instead of `contact = data;`? – trincot Jul 26 '16 at 15:03
  • `static t;` is not ES6. Are you using typescript or something? – Bergi Jul 26 '16 at 15:16
  • 2
    You should not store promise results as instance properties anyway. Store the promise if you need to. – Bergi Jul 26 '16 at 15:18
  • @trincot no, `this` inside the promise no longer refers to the class. That was my first attempt :) – Andrew Grothe Jul 26 '16 at 18:36
  • @Bergi, not typescript. Some experimental features turned on though. – Andrew Grothe Jul 26 '16 at 18:37
  • @Bergi Aurelia needs a property to bind to. The `activate` method returns a promise so that the screen waits for the data before loading. Once loaded, the binding needs a property. Or so I understand it thus far. – Andrew Grothe Jul 26 '16 at 18:57
  • @agrothe: OK it always depends on how you are using the property of course. If Aurelia cannot render promises directly, you might need it, but always keep in mind that it might be `undefined` when the promise is not fulfilled. – Bergi Jul 26 '16 at 19:02

2 Answers2

25

You need to do two things. First, use an arrow function, and second, use `this.contact = data;

activate(id) {
  this.id = id;
  return dpd.contacts.get(id).then(data => {
    console.log(data);
    this.contact = data;
  });
}

You use an arrow function because it deals with JavaScript's "this" issue, where this refers to the lexical scope of the function, and not the object you're currently in. Using an arrow function makes sure that this outside the arrow function is the same as this inside the arrow function.

You need to use this.contact because contact is an instance property of the class.

Ashley Grant
  • 10,879
  • 24
  • 36
7

The problem is that contact = data; will update the value of the local contact variable, but will not change the value of the this.contact. You need to update the contact contact property instead. The problem is that you do not have access to this inside the body of your anonymous function (or rather, the this of the anonymous function is not going to be the same this as activate's).

There is different ways to solve this.

1- You can save activate's context (this) into a variable in the closure of activate so that you can access it inside the core of then.

activate(id) {
    this.id = id;
    let that = this;
    return dpd.contacts.get(id).then(function(data) {
      console.log(data);
      that.contact = data;
    });
  }

2- You can bind the function to activate's this so that it is called with the same context.

activate(id) {
    this.id = id;
    return dpd.contacts.get(id).then(function(data) {
      console.log(data);
      this.contact = data;
    }.bind(this));
  }

3- (recommended with ES6) you can use an arrow function (arrow functions do not have their own context, so they preserve the one where they are created)

activate(id) {
    this.id = id;
    return dpd.contacts.get(id).then((data) => {
      console.log(data);
      this.contact = data;
    });
  }
Quentin Roy
  • 7,677
  • 2
  • 32
  • 50
  • I had already tried #1 with no luck. Going to try #2 though to see how that works. #3 works. – Andrew Grothe Jul 26 '16 at 18:43
  • #1 and #2 also work. My error was using `let contact = this.contact`. Apparently that won't work where as `let that = this` does work. Odd, but I'll take it. – Andrew Grothe Jul 26 '16 at 18:47
  • This is not odd. If you do `contact = something`, you are assigning a new value to the `contact` **variable**. You are not modifying the previous value that were assigned to it. What you are trying to do is to change the `contact` property of the `this` object. This property is unrelated to the `contact` variable (apart from the fact that you initialise its value to the value pointed by `this.contact`). The only way to change the value pointed by the property `prop` of an object `obj` is by writing something similar to `obj.prop = something`. – Quentin Roy Aug 05 '16 at 07:15