Angular data access service
Introduction
This is a page just to remind me how to create a service for angular
Setting Up In Memory Web API
- Data Configuration
- Install In Memory Web API
- Configure in module
Data Configuration
import { InMemoryDbService } from 'angular-in-memory-web-api';
import { Product } from './product';
export class ProductData implements InMemoryDbService {
createDb(): { products: Product[]} {
const products: Product[] = [
{
id: 1,
productName: 'Leaf Rake',
productCode: 'GDN-0011',
releaseDate: 'March 19, 2018',
description: 'Leaf rake with 48-inch wooden handle',
price: 19.95,
starRating: 3.2,
imageUrl: 'assets/images/leaf_rake.png',
tags: ['rake', 'leaf', 'yard', 'home']
},
{
id: 2,
productName: 'Garden Cart',
productCode: 'GDN-0023',
releaseDate: 'March 18, 2018',
description: '15 gallon capacity rolling garden cart',
price: 32.99,
starRating: 4.2,
imageUrl: 'assets/images/garden_cart.png'
},
{
id: 5,
productName: 'Hammer',
productCode: 'TBX-0048',
releaseDate: 'May 21, 2018',
description: 'Curved claw steel hammer',
price: 8.9,
starRating: 4.8,
imageUrl: 'assets/images/hammer.png',
tags: ['tools', 'hammer', 'construction']
},
{
id: 8,
productName: 'Saw',
productCode: 'TBX-0022',
releaseDate: 'May 15, 2018',
description: '15-inch steel blade hand saw',
price: 11.55,
starRating: 3.7,
imageUrl: 'assets/images/saw.png'
},
{
id: 10,
productName: 'Video Game Controller',
productCode: 'GMG-0042',
releaseDate: 'October 15, 2018',
description: 'Standard two-button video game controller',
price: 35.95,
starRating: 4.6,
imageUrl: 'assets/images/xbox-controller.png'
}
];
return { products };
}
}
Install In Memory Wep API
npm install angular-in-memory-web-api --save-dev
Configure in module
import { NgModule } from '@angular/core';
...
// Imports for loading & configuring the in-memory web api
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { ProductData } from './product-data';
...
@NgModule({
imports: [
...
InMemoryWebApiModule.forRoot(ProductData),
Service creation
We create a service by using the @Injectable and provide where in the application it is injected into. In this case the root
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { catchError, tap, map } from 'rxjs/operators';
import { Product } from './product';
@Injectable({
providedIn: 'root'
})
export class ProductService {
private productsUrl = 'api/products';
constructor(private http: HttpClient) { }
getProducts(): Observable<Product[]> {
return this.http.get<Product[]>(this.productsUrl)
.pipe(
tap(data => console.log(JSON.stringify(data))),
catchError(this.handleError)
);
}
getProduct(id: number): Observable<Product> {
if (id === 0) {
return of(this.initializeProduct());
}
const url = `${this.productsUrl}/${id}`;
return this.http.get<Product>(url)
.pipe(
tap(data => console.log('getProduct: ' + JSON.stringify(data))),
catchError(this.handleError)
);
}
createProduct(product: Product): Observable<Product> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
product.id = null;
return this.http.post<Product>(this.productsUrl, product, { headers })
.pipe(
tap(data => console.log('createProduct: ' + JSON.stringify(data))),
catchError(this.handleError)
);
}
deleteProduct(id: number): Observable<{}> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
const url = `${this.productsUrl}/${id}`;
return this.http.delete<Product>(url, { headers })
.pipe(
tap(data => console.log('deleteProduct: ' + id)),
catchError(this.handleError)
);
}
updateProduct(product: Product): Observable<Product> {
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
const url = `${this.productsUrl}/${product.id}`;
return this.http.put<Product>(url, product, { headers })
.pipe(
tap(() => console.log('updateProduct: ' + product.id)),
// Return the product on an update
map(() => product),
catchError(this.handleError)
);
}
private handleError(err): Observable<never> {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
let errorMessage: string;
if (err.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
errorMessage = `An error occurred: ${err.error.message}`;
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
errorMessage = `Backend returned code ${err.status}: ${err.body.error}`;
}
console.error(err);
return throwError(errorMessage);
}
private initializeProduct(): Product {
// Return an initialized object
return {
id: 0,
productName: null,
productCode: null,
tags: [''],
releaseDate: null,
price: null,
description: null,
starRating: null,
imageUrl: null
};
}
}
iwiseman@oliver:~/dev/vscode/angular/Angular-R