This is how you do a proper use of async pipe. When you use async pipes you don't have to subscribe because they do the lifcycle of an observable for you. The subscribe and destroy the subscription to avoid memory leaks. If you don't use async pipes you have to do this manually.
SERVICE.TS
import { EquipmentID } from './../../../shared/model/equipmentID.model';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { PickupAvailability } from '../models/pickup-availability.model';
import { catchError } from 'rxjs/operators';
import { ErrorHandlingService } from '../../../shared/services/error-handling.service';
@Injectable()
export class PickupAvaibilityService {
BASE_URL = '/sxrw-ship/api/v1';
AMOUNT_DUE_URL = '/shipments/search';
constructor(
private http: HttpClient,
private errorHandler: ErrorHandlingService
) {}
getAmountDue(equipmentID: EquipmentID[]): Observable<PickupAvailability> {
return this.http
.post<PickupAvailability>(
this.BASE_URL + this.AMOUNT_DUE_URL,
equipmentID
)
.pipe(catchError(this.errorHandler.handleError));
}
}
Then in my custom error handler service you will have something like this:
ERRORHANDLER.SERVICE.TS
import { Injectable } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { _throw } from 'rxjs/observable/throw';
@Injectable()
export class ErrorHandlingService {
constructor() {}
handleError(error: HttpErrorResponse) {
//To know the version of RxJS npm list --depth=0 (I for this example im on version 5.5)
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
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.message}`
);
}
// return an observable with a user-facing error message
return _throw('Something bad happened; please try again later.');
}
}
The way I did my error handler is the way it is done on the Angular's official website https://angular.io/guide/http
Now, in the component that will be using the service that calls us http you declare a variable of type Observable (it's good practice to use the $ sing)
COMPONENT.TS
pickupAvailability$: Observable<PickupAvailability>;
getPickupDate(pa: PickupAvailability) {
let id = pa.equipmentInitial + pa.equipmentNumber;
this.equipmentSummary$ = this.pickupDateService
.getPickupDate(id)
.pipe(
map(
pd =>
new EquipmentSummary(
id,
pd.pickupDate,
'TODO',
pa.totalPremiseCharges
)
)
);
}
HTML
<div *ngIf="(pickupAvailability$ | async) as pickupAvailability">
<!-- TODO move to table -->
<div *ngFor="let pa of pickupAvailability">
<button pButton type="button" label="Pay ${{ pa.totalPremiseCharges }}" class="x-primary-gray-100" (click)='getPickupDate(pa)'>
</button>
</div>
<div *ngIf="(equipmentSummary$ | async) as es">
<app-pay-storage [equipmentSummary]="es"></app-pay-storage>
</div>
</div>
You can test it by doing this:
{{pickupAvailability$ | async | json}}
when you are actually going to use it remove the json pipe