hannahhoward / a1atscript

The Angular 2 Polyfill
MIT License
101 stars 7 forks source link

'this' context in event handlers should be a reference to the class where the handler lives #7

Open timkindberg opened 9 years ago

timkindberg commented 9 years ago

When I'm using the Component events config it hooks up the handler with an incorrect this context. I would expect this to reference the App class instance, but it actually references the Home class instance.

@Component({
  selector: 'home'
})
@View({
  template: "<p>Home</p>",
  // Here I'm setting up a 'foo' event
  events: {
    foo: "foo"
  }
})
class HomeComponent {
  constructor() {
    // See here that I'm adding a property to Home
    this.wtf = "wat?";
  }
}

@AsModule('AppModule', [HomeComponent])
@Component({
  selector: "app"
})
@View({
  // Here I'm using the on-foo event and passing a reference to the App's doFoo method
  inline: `<home on-foo="doFoo"></home>`
})
class AppComponent {
  doFoo() {
    // Here is where things fell apart for me and 'this' was not what I expect
    console.log(this) // HomeComponent {wtf: "wat?"}, expected an instance of AppComponent
  }
}

bootstrap(AppComponent)
hannahhoward commented 9 years ago

Yes. this is a somewhat known bug (I did a quick and dirty implementation of the events -- should have noted this problem since I knew about it when it was implemented). Unfortunately it's not exactly easy to fix given Angular 1.x's way of working. I intend to give it a fix, but it may take a bit.

hannahhoward commented 9 years ago

The work around for now is to bind the function before you pass it. i.e. for the class you listed:

class AppComponent {
  constructor() {
     this.doFoo.bind(this);
  }

  doFoo() {
    console.log(this) // should still be AppComponent
  }
}
timkindberg commented 9 years ago

Thanks for responding! For now we are ditching the formal usage of classes and just writing everything in the class constructor. That allows me to use the let self = this; reference.