RajGan
RajGan

Reputation: 861

Angular 7 Typescript - Service ErrorHandle losing object instance

I am trying to display an error message [ngBootstrap Alert] when I get 404 or 500 from Service api call.

I want to display error thru alertComponent and I use service for data sharing [AlertService.ts].

When my call to api return 404 I catch error and call handleError Method which is defined in my service Base class.

The issue is I injected my Alert service in my Base class and when I call HandleError method the alert variable loses its instance and is set to undefined.

BaseService.ts

@Injectable({
  providedIn: 'root'
})
export abstract class BaseService {

  constructor(msgService: AlertService) { }

  public handleError(httpErrorResponse: HttpErrorResponse) {

    console.log(httpErrorResponse);

    let errorMessage = '';
    switch (httpErrorResponse.status) {
      case 400:
        errorMessage = 'Bad Request detected; please try again later!';
        break;
     case 404:
        const errorMsg = new Alert(AlertType.Danger, 'tracking-not-found');
        this.msgService.Add(errorMsg);
        break;
      case 500:
        errorMessage = 'Internal Server Error; please try again later!';
        break;
      default:
        errorMessage = 'Something bad happened; please try again later!';
        break;
    }
    return throwError(errorMessage);

  }

ChildService.ts

    @Injectable({
      providedIn: 'root'
    })
    export class ChildService extends BaseService {
    constructor(alertService: AlertService){
    super(alertService)
    }

    callApiMethod (){
     return this.http.get<Brand>(`ApiUrl`).pipe(

          catchError(this.handleError)
        );
     }
  }

AlertService.ts

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

  alertMsg: Alert;
  constructor() { }

  public clear() {
    console.log('alert cleared');
    this.alertMsg = null;
  }

  public Add(alert: Alert) {
    this.alertMsg = alert;
  }
}

Alert.ts

export class Alert {
  constructor(public alertType: AlertType,
    public msgCode: string,
    public icon?: string) { }
}

export enum AlertType {
  Success = 'success',
  Info = 'info',
  Warning = 'warning',
  Danger = 'danger',
}

When I try to call Add method from AlertService I get following Error

TypeError: Cannot read property 'Add' of undefined

I see the msgService variable is set to undefine somehow. Any Help?

Upvotes: 3

Views: 247

Answers (3)

Xesenix
Xesenix

Reputation: 2548

I guess your problem lies in not binding:

@Injectable({
  providedIn: 'root'
})
export class ChildService extends BaseService {
  constructor(alertService: AlertService){
    super(alertService)
  }

  callApiMethod (){
    return this.http.get<Brand>(`ApiUrl`).pipe(
      catchError(this.handleError.bind(this)) // here we need to either bind or use arrow function
    );
  }
}

That is if your error is caused by that line in this.msgService.Add(errorMsg); in BaseService.

Upvotes: 5

RajuPedda
RajuPedda

Reputation: 3379

You need to use access modifier (public / private) in ChildService and BaseService, so that your service reference will available with the property.

ChildService

@Injectable({
  providedIn: 'root'
})
export class ChildService extends BaseService {
constructor(**private alertService**: AlertService){
super(alertService)
}

BaseService

 @Injectable({
  providedIn: 'root'
})
export abstract class BaseService {

  constructor(**private msgService**: AlertService) { }

}

Upvotes: 0

yanky_cranky
yanky_cranky

Reputation: 1363

You need to define the access specifier of the service in the constructor of BaseService Class :

constructor(private msgService: AlertService) { }

then only you will be able to do "this.msgService" and it won't come undefined.

Cheers (y)

Upvotes: 1

Related Questions