Angular7 REST API Client Service An example of an Angular7 service for calling a REST API for Get/Save/Delete (assumes both save and delete use post). Includes cache-busting, UI messages, and error handling. Assumes you have some service 'notification' injected which logs or shows errors. Assumes posts always return a PostResult (custom) class. _____________________ import { Injectable } from '@angular/core'; import { Observable, of, throwError } from 'rxjs'; import { catchError, map, finalize } from 'rxjs/operators'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { NotificationService } from './notification.service'; import { ActivatedRoute } from '@angular/router'; @Injectable() export class AppAPIService { constructor(private http: HttpClient, private notification: NotificationService) { } // get via url, adding 'r' as timestamp to avoid cache getR(url: string, component: AppComponent): Observable<any> { if (component != null) component.loadingCount++; if (url.indexOf('?') > 0) url += '&r=' + new Date().getTime(); else url += '?r=' + new Date().getTime(); return this.http.get(url) .pipe( finalize(() => { if (component != null) component.loadingCount--; }), catchError(this.handleError<any>())) } // get via url get(url, component: AppComponent): Observable<any> { if (component != null) component.loadingCount++; return this.http.get(url) .pipe( finalize(() => { if (component != null) component.loadingCount--; }), catchError(this.handleError<any>())) } // save, adding 'r' as timestamp to avoid cache saveR(isValid: boolean, entityToSave: any, component: AppComponent, url: string): Observable<PostResult> { if (isValid && !component.savingData) { component.savingData = true; component.saveResultMessage = ''; component.errorMessage = ''; if (url.indexOf('?') > 0) url += '&r=' + new Date().getTime(); else url += '?r=' + new Date().getTime(); return this.http.post<PostResult>(url, entityToSave) .pipe( map(value => { if (value.Success) { this.notification.success('Successfully Saved!'); component.saveResultData = value.ResultData; // in case needed component.saveResultMessage = value.OutputMessage; component.errorMessage = ''; } else { component.errorMessage = 'Save failed: ' + value.ErrorMessage; } component.savingData = false; return value; }), catchError(this.handlePostError<any>(component))); } } // delete, adding 'r' as timestamp to avoid cache deleteR(entityTitle: string, entityToDelete: any, component: AppComponent, url: string, actionName?: string): Observable<any> { if (actionName == null || actionName == '') actionName = 'Deleted'; if (entityTitle == null || entityTitle == '') entityTitle = 'Record'; if ((!component.savingData) && confirm(entityTitle + ' will be ' + actionName + '; OK to proceed?')) { component.savingData = true; if (url.indexOf('?') > 0) url += '&r=' + new Date().getTime(); else url += '?r=' + new Date().getTime(); return this.http.post<PostResult>(url, entityToDelete) .pipe( map(value => { if (value.Success) { this.notification.success('Successfully ' + actionName + '!'); component.errorMessage = ''; } else { component.errorMessage = value.ErrorMessage; } component.savingData = false; return value; }), catchError(this.handlePostError<any>(component))); } } private handlePostError<T>(component: AppComponent) { return (error: any): Observable<T> => { component.savingData = false; this.notification.error(error.message == null ? error : (error.message + ' ' + error.error)); return throwError(error); } } private handleError<T>() { return (error: any): Observable<T> => { this.notification.error(error.message == null ? error : (error.message + ' ' + error.error)); return throwError(error); } } } // class export class AppComponent { savingData = false; errorMessage: string; saveResultMessage: string; saveResultData: string; loadingCount = 0; isLoading() { return this.loadingCount > 0; } } class PostResult { Success: boolean; ResultData: string; OutputMessage: string; ErrorMessage: string; }
Created By: amos 1/16/2020 9:18:55 AM
|
|