Why do Actions functions not have access to the component


#1

I have noticed that if I have the following:

export default Ember.Component.extend({ actions: { clickButton() { this.transitionToRoute(‘user.roomviewer’); } } });

The clickButton action has no access to the transitionToRoute function because it can’t see the component. It only sees “this” as what is declared in the contents of this file or what is implicitly added in other ways.

Why can’t actions allowed to see the component? I’ve never understood this!


#2

Ok transitionToRoute was a bad example for the function as its not accessible anyway


#3

with get you should have access to them. to get transition into components you hav to inject the route service


#4

That’s what I mean though, why do I have to call .get, why can’t it just be the same ‘this’ scope. I find it inconsistent.


#5

many binding things (observer for example) happen with get and set… its not a bad thing to use it. and pure this is not in class scope when usung it inside action.

i recommend to use it like so…

import {get} from Ember; … get(this, “foo”)…


#6

I do use it when I know it has binding on it. But if I’m just calling a function it seems silly to do this.get(‘myfunc’)() only from actions but not from within the class itself.


#7

Bit confused. Actions by default have the context of the component they are defined in. The only exception is when the action is overridden using an action closure.

{{foo}}
<button {{action "tryThis"}}>Click</button>

export default Ember.Component.extend({
  fo: 'bar',
  exampleFunction() {
    this.set('foo', 'baz');
  },
  actions: {
    tryThis() {
      this.exampleFunction();
    }
  }
});

This all works. https://ember-twiddle.com/e78b3b8ea504db66363f7b5681d26961


#8

It does generally work, but in a certain scenario it becomes difficult to access the service.

For instance, if I have an event click handled in a component, then you call the service function, then in that function in the service the “this” no longer points to the service. Or something like that, when I come across it again I’ll post here the code. But I end up having to jump through silly hoops.


#9

I’ve come across this again.

I’m in a component class function, with a jquery asynchronous call inside it

simplifying:

export default Ember.Component.extend({

catalogueHooks: Ember.inject.service(),

e.g LoadPlan() { var service = this.get(‘catalogueHooks’); Ember.$.when( API ).then(function(plan) { service.get(‘setPlanData’)(JSON.parse(plan.plandata)); }); }

Then inside that setPlanData function in the service, “this” does not exist it is undefined. e.g setPlanData(value) {

alert("context:"+ this); // undefined this
	var list = this.get('storedData.plans');
	list[this.get('currentPlanIndex')].plan = value;
	this.set('storedData.plans', list);
	return value;
},

I suspect that this is my poor knowledge of general javascript scoping coming into play, I have the vaguest notion of ‘enclosure’ but to me if you call a function of an object, the “this” should be the instance that owns the function. I end up having to pass the service function a copy of he service itself. Which is nasty hack.


#10

Found my problem in this particular case, it was the this.get() on the service, instead of just calling the function directly.

Getting too habitual with the calling of parent component actions.

I’m not 100% I was doing this before though so my issue still might be around


#11

You are defining a new function after the api call returns which has its own “this”:

Ember.$.when(API).then( function(plan) {
  // "this" has a new context
});

With the new arrow functions syntax (description of this problem in section “No binding of this”) your “this” keeps the same context.

Ember.$.when(API).then( (plan) => {
   // "this" has the same context as before
});

#12

Thanks for that information