Data Browser - Viewing Site  Sector 23 Code Bank Logged in as:  Guest  




           


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