I have a component which calls a service to fetch data from a RESTful endpoint. This service needs to be given a callback function to execute after fetching said data.
The issue is when I try use the callback function to append the data to the existing data in a component's variable, I get a EXCEPTION: TypeError: Cannot read property 'messages' of undefined
. Why is this
undefined?
TypeScript version: Version 1.8.10
Controller code:
import {Component} from '@angular/core' import {ApiService} from '...' @Component({ ... }) export class MainComponent { private messages: Array<any>; constructor(private apiService: ApiService){} getMessages(){ this.apiService.getMessages(gotMessages); } gotMessages(messagesFromApi){ messagesFromApi.forEach((m) => { this.messages.push(m) // EXCEPTION: TypeError: Cannot read property 'messages' of undefined }) } }
Use the Function.prototype.bind function:
getMessages() { this.apiService.getMessages(this.gotMessages.bind(this)); }
What happens here is that you pass the gotMessages
as a callback, when that is being executed the scope is different and so the this
is not what you expected.
The bind
function returns a new function that is bound to the this
you defined.
You can, of course, use an arrow function there as well:
getMessages() { this.apiService.getMessages(messages => this.gotMessages(messages)); }
I prefer the bind
syntax, but it's up to you.
A third option so to bind the method to begin with:
export class MainComponent { getMessages = () => { ... } }
Or
export class MainComponent { ... constructor(private apiService: ApiService) { this.getMessages = this.getMessages.bind(this); } getMessages(){ this.apiService.getMessages(gotMessages); } }
Or you can do it like this
gotMessages(messagesFromApi){ let that = this // somebody uses self messagesFromApi.forEach((m) => { that.messages.push(m) // or self.messages.push(m) - if you used self }) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With