-1

I will get an image from backend in my Angular 12 application with this function:

getProfileImage(filename: string, userId: string, callback) {
        const url = environment.apiEndpoint + 'files/profileimage/' + filename + '/' + userId;
        var xhr = new XMLHttpRequest();
        xhr.onload = function () {
            var reader = new FileReader();
            reader.onloadend = function () {
                callback(reader.result);
            }
            reader.readAsDataURL(xhr.response);
        };
        xhr.open('GET', url);
        xhr.responseType = 'blob';
        xhr.send();
    }
}

I invoke this function like this

ngOnInit() { 
    this.authService.getUser().then(response => {
      this.user = response;

      this.profileService.getProfileImage(this.user.profileImagePath, this.user.id, function(dataUrl) {
        this.profileImage = dataUrl;  // here I get an error
        console.log(this.profileImage);
      });
    });
  }

The error I get is:

core.js:6479  ERROR TypeError: Cannot set properties of undefined (setting 'profileImage')
    at profile.page.ts:29:26
    at reader.onloadend (profile.service.ts:23:17)
    at push.99140._ZoneDelegate.invoke (zone.js:409:1)
    at Object.onInvoke (core.js:28705:1)
    at push.99140._ZoneDelegate.invoke (zone.js:408:1)
    at push.99140.Zone.runGuarded (zone.js:180:1)
    at FileReader.<anonymous> (zone.js:163:1)

So my question is how to assign datgaUrl response to an component variable (which is reachable in html code)

quma
  • 5,233
  • 26
  • 80
  • 146
  • That's because you're using the `function` keyword to declare the function, which messes `this`. Swap it for an arrow function and you should be fine. – Allan Juan Jul 15 '23 at 16:19
  • Does this answer your question? [How to access the correct \`this\` inside a callback](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – jonrsharpe Jul 15 '23 at 16:22
  • Thanks for the answer! Could you give me anonther hint how to do it with arrow function. I am pretty new to RxJS. Thanks! – quma Jul 15 '23 at 16:22

2 Answers2

0

Use an arrow function to keep the this context :

this.profileService.getProfileImage(this.user.profileImagePath, this.user.id,(dataUrl) => { // here an () => {}
        this.profileImage = dataUrl;  // You'll be fine here
});
Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
0

You could try to do like this

var self = this; //in this way you save the context
this.profileService.getProfileImagethis.user.profileImagePath, this.user.id, function(dataUrl) {
    self.profileImage = dataUrl;
    
  });

Doing this, you will save the context in a variabile and you can use it to access the component context.

This is like Matthieu said, but in this way you explicitly declare that "self" variable, otherwise it's created by JavaScript. Hope it helps!