Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ember "this" undefined in component

I'm trying to make a progress bar that gets updated as more challenges are completed. However, the component cannot access the property because this is undefined.

I have injected a service and I'm trying to create a computed property from a property of the service. However, this is always undefined unless in debugging.

import Ember from 'ember';

export default Ember.Component.extend({
  progress: 0,
  game: Ember.inject.service(),
  events: this.get("game.challenges")
});

How can this be undefined in the above code? How is it not bound to any scope?

I've thrown in a debugger like this:

init() {
  debugger
},

If I log out this.get("game") it returns the expected value.

I've also tried putting in the service inside of the init, still undefined. I've tried logging out this and that is undefined as well.

Is there a way to force the service to resolve before moving on? I have tried using various component hooks but they don't seem to have changed things.

like image 244
user3162553 Avatar asked Nov 08 '15 19:11

user3162553


1 Answers

Elaborating on Tom's answer:

In JS, this is kind of a special variable. Its meaning depends on whether it is inside a function or not.

  • Outside a function, it is the global context (in a browser, that's usually the window object).
  • Inside a function, it is the object the function is called on. Eg if you write obj.f(), then this will be obj in f(). If calling the function directly, this remains whatever it currently is.

In your code, the JS engine is currently executing outside a function (it is preparing to call extend, passing it an object).

export default Ember.Component.extend({
  game: Ember.inject.service(),
  events: this.get("game.challenges")
});

Therefore, this in your code refers to the window object. You fix that using a computed property, that is, a function that gets invoked on your object when the property is accessed:

export default Ember.Component.extend({
  game: Ember.inject.service(),
  events: Ember.computed('game.challenges', function() {
    return this.get("game.challenges");
  })
});

You may do whatever computation you need in the function. Just remember than anything the result depends on must be listed inside property() so Ember knows when to recompute it.

Lastly, for some common cases, ember provides some shortcuts, such as Ember.computed.alias, Ember.computed.equal, …

like image 72
spectras Avatar answered Sep 28 '22 05:09

spectras