0

I have tried Googling this, but have got nowhere... ;-)

I have written some Angular 9 code, where my Component calls a Service which I've injected.

If I call one of the Service's functions directly, then it all works fine:

@Injectable()
export abstract class MikesBaseClass {

    saveToDatabase = () => {
        this.staticDataService.putContact(this.selectedRow).subscribe(
           data => {
                //  ... handle the result from the webservice
            }); 

Problem is, I'm trying to make this generic, and need to be able for Components which inherit from this base class to pass it the function which needs to be called. So, the code will actually look more like this:

@Injectable()
export abstract class MikesBaseClass {

  //  This is the function I want to call, when I'm ready to call my "PUT" webservice
  updateRecord = this.staticDataService.putContact;

  saveToDatabase = () => {
      this.updateRecord(this.selectedRow).subscribe(
          data => {
              //  ... handle the result from the webservice
          });

When I run this code, it does call the correct function in my Service, but the "this" value is the "this" from MikesBaseClass, rather than from the StaticDataService.

@Injectable({
    providedIn: 'root',
  })
export class StaticDataService {

    private contactsUrl = 'https://somewebsite.com/api/Persons';

    putContact(newRecord: any): Observable<any> {
        let body = JSON.stringify(newRecord);
        return this.http.put(this.contactsUrl, body, this.httpOptions)
                        .catch(this.defaultErrorHandler('Updating Contacts record'));
    }

So, it fails as "this.http" doesn't exist, it can't find "this.contactsUrl", etc etc.

If I were to use "this.staticDataService.http" or "this.staticDataService.contactsUrl", that'd work fine though.

So basically, when the "putContact" is being run in this way, it's got the "this" from my Component, rather than my Service.

How can I fix this ?

(I'm sure its a simple one-line fix...)

Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159

1 Answers1

0

Damn it... it was easier than expected.

I just needed to change the "updateData" variable to be a lambda expression:

@Injectable()
export abstract class MikesBaseClass {

  //  This is the function I want to call, when I'm ready to call my "PUT" webservice
  updateRecord = (data) =>  this.staticDataService.putContact(data);

  saveToDatabase = () => {
      this.updateRecord(this.selectedRow).subscribe(
          data => {
              //  ... handle the result from the webservice
          });

I'll leave this in StackOverflow, just in case anyone else hits this problem.

Update

A couple of people have said that, actually, this question had already been answered here:

How to access the correct `this` inside a callback?

I genuinely disagree.

The solution to my problem was to replace this:

updateRecord = this.staticDataService.putContact;

.. with this...

updateRecord = (data) =>  this.staticDataService.putContact(data);

... and I'm sorry, but no... I really wouldn't have found that out, using the other article. And I do think this StackOverflow article is worth leaving here, in the hope that it helps other developers.

This subtle change in syntax is not obvious, and I think this article does add value.

Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159