Reputation: 1181
I'm trying to set snackbar from material2 as error catcher for angular2 services. Seems to me I did everything correct but still getting an error
EXCEPTION: Uncaught (in promise): TypeError: Cannot read property 'notify' of undefined TypeError: Cannot read property 'notify' of undefined
This is my services with my catcher:
import { Injectable } from '@angular/core';
import {Headers, Http, RequestOptions} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Observable} from 'rxjs/Rx';
import {MdSnackBar, MdSnackBarConfig, MdSnackBarRef} from '@angular/material';
@Injectable()
export class AppServices {
private api = 'app/endpoint';
private headers = new Headers({ 'Content-Type': 'application/json' });
private options = new RequestOptions({ headers: this.headers });
constructor(
private http: Http,
private snackbar: MdSnackBar
) { }
getConfigs(): Promise<any> {
return this.http
.get(this.api + "/confs")
.toPromise()
.then(response => response.json() as Array<Object>)
.catch(this.handleError)
}
// ==============
// errors handler
// ==============
notify (status: any, text: any) {
this.snackbar.open(status, text, {
duration: 3000
});
}
public handleError(error: Response) {
this.notify(error.status, error.statusText);
return Observable.throw(error.json() || 'Server error');
}
}
So when catcher gets an error instead of snakebar I get the error in console that my function is undefined.
Could somebody explain me where my mistake is? Thanks in advance
Upvotes: 1
Views: 2580
Reputation: 13397
You are losing scope within your .catch()
statement. When the asynchronous .catch()
method was executing, it is attaching it's own scope to this
.
Using an arrow function like so:
.catch((err)=>{this.handleError(err);})
Will ensure that your scope is maintained through the asynchronous method calls and typically good practice these days with TS to avoid this
hell.
The arrow function syntax uses “lexical scoping” to figure out what the value of this
should be. Lexical scoping is fancy way of saying it uses this
from the surrounding code.
If you're interested in reading more about arrow functions and lexical scoping, this is a good article.
The interesting thing to note is that the
this
value (internally) is not actually bound to the arrow function. Normal functions in JavaScript bind their ownthis
value, however thethis
value used in arrow functions is actually fetched lexically from the scope it sits inside. It has nothis
, so when you use this you’re talking to the outer scope.
Upvotes: 6