Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open angular material Snackbar in service

I want to show the user Errors through a Snackbar. Which is totally fine when I open a Snackbar through a component:

export class AppComponent implements OnInit {

    constructor(private snackBar: MatSnackBar) {
    }

    ngOnInit() {
        this.snackBar.open('message');
    }
}

But when I want to open a Snackbar in my DataService it throws this error:

ERROR TypeError: Cannot read property 'open' of undefined

My DataService looks like this:

export class DataService {

  private api = 'https://localhost:5001/api/';

  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  };

  constructor(private http: HttpClient,
              private snackBar: MatSnackBar) {
  }

  getData() {
    return this.http.get(this.api, this.httpOptions)
      .pipe(
        retry(3), // retry a failed request up to 3 times
        catchError(this.handleError) // then handle the error
      );
  }

  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }

    this.snackBar.open('Something bad happened, please try again later.');

    // return an observable with a user-facing error message
    return throwError(
      'Something bad happened; please try again later.');
  }
}

So, after the third attempt of getting Data it goes into the handleError() and should open a SnackBar with "Something bad happened, please try again later."

like image 565
tidi00 Avatar asked Feb 02 '19 15:02

tidi00


1 Answers

This happens because the current scope inside catchError is not the class itself and thus

this.snackbar

is not defined. To fix this, there are 2 methods

Method 1:

You can return your callback function from inside another function to preserve the scope as

private handleError() {
    return (error: HttpErrorResponse) => {
        //your logic
    }
}

and change your catchError method as

catchError(this.handleError())  //note the parenthesis on handleError

Method 2:

Simply bind the callback method in catchError to this as

this.ErrorHandler.bind(this)
like image 119
Saksham Avatar answered Sep 19 '22 12:09

Saksham