1

I have created an Angular 7 component that has an observable from an angular service. I am using it to bind data from a remote service to a list on one of my pages. It works pretty good. However, one thing I noticed is in the subscribe asynchronous callback if I use a named function instead of an anonymous function the data does not bind to the list on my page.

Here is an example of the current anonymous callback which works

public constructor(private vendorApiService: VendorApiService,
    private eventMessagingService: EventMessagingService) {

    this.vendorApiService.getVendors().subscribe(
      (data) => {
        this._vendor = data;
        this.dataSource = new MatTableDataSource<Vendor>(this._vendor);
        this.dataSource.paginator = this.paginator;
      });
    this._displayedColumns = ['id', 'code', 'name', 'edit'];
}

I would like to convert it to this. However, this does not work:

public constructor(private vendorApiService: VendorApiService,
  private eventMessagingService: EventMessagingService) {

    this.vendorApiService.getVendors().subscribe(
      this.setup_vendor_list);
    this._displayedColumns = ['id', 'code', 'name', 'edit'];
}

private setup_vendor_list(data) {
  this._vendor = data;
  this.dataSource = new MatTableDataSource<Vendor>(this._vendor);
  this.dataSource.paginator = this.paginator;
}

Based on what I know about Javascript this should work. However, since this is typescript, there may be some special condition I am not aware of that impacts the way named and anonymous callbacks are handled.

If you can explain the difference, please do so.

Gonçalo Peres 龚燿禄
  • 4,208
  • 3
  • 18
  • 51
thxmike
  • 380
  • 1
  • 3
  • 14
  • what are you getting in the second scenario ? – Nikolai Kiefer Dec 02 '18 at 23:09
  • Add a `console.log` and try to log `this` in your function. Arrow functions don't change the value of `this`, but named functions do. It's probably the reason why it won't work. You can, however, pass an arrow function that calls your function instead, as in `(data) => setup_vendor_list(data)`. – Paulo Avelar Dec 02 '18 at 23:12

1 Answers1

2

It's not about TypeScript, it's still pure JavaScript issue. Passing this.setup_vendor_list as a an argument is the same as passing

function (...args) { return this.setup_vendor_list(...args) },

which is not the same as

(...args) => this.setup_vendor_list(...args),

which you seem to believe.

It's also not about named vs anonymous functions: notice how both of my examples are anonymous. However, only one is an arrow function.

The difference which affects you is the way this is resolved inside these functions, which you can read more about in How does the "this" keyword work?.


Two quickest workarounds:

subscribe(this.setup_vendor_list.bind(this))
subscribe(data => this._setup_vendor_list(data))
Lazar Ljubenović
  • 15,745
  • 7
  • 45
  • 80
  • Yes, you are correct about "this". I should have realized this. I sometimes forget about "this" context. Thanks for the assist. – thxmike Dec 03 '18 at 00:38