Thursday, June 21, 2018

A10–Building App using Angular and ASP.NET Core 2.1–Services, Events and Cross Component Communication

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, A5, A6, A7, A8, A9 Github Repo
Today, I was able to accomplish few things,
1. Added Shopping service that adds product and updates shopping cart
2. Established cross component communication via Shopping Service (Home Component –> Add To Cart –> Updates Shopping Cart
3. Created API for adding and getting products from ShoppingCart Controller. I am returning hard coded products and hence you will always see two shown at the top right.
Right now I didn’t wanted to create any database backend. I want to just make sure client server interaction is in sync. Once I like how everything is structured then I will invest time into adding database layer. Below is code for Shopping Service.
import { Injectable, Inject } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Product } from '../product/product';
import { catchError, map, tap,last } from 'rxjs/operators';
import 'rxjs/add/observable/throw';
import { of } from 'rxjs/observable/of';
import { Observable } from 'rxjs/Observable';
const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
  })
};
@Injectable()
export class ShoppingService {

  private _baseUrl: string;
  private cartQuantitySource = new BehaviorSubject(0);
  currentCartQuantity = this.cartQuantitySource.asObservable();

  private _addProductToShoppingCart: string = "api/ShoppingCart/Add/";
  private _getProductsFromShoppingCart: string = "api/ShoppingCart/Products";
  constructor(private _http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this._baseUrl = baseUrl;
    this.updateCartQuantity(); 
  }

  updateCartQuantity() {
    this._http.get<Product[]>(this._baseUrl + this._getProductsFromShoppingCart).subscribe(products => {
      this.log(`getting products from shopping cart`);
      this.cartQuantitySource.next(products.length);
    });
  }

  addProductToCart(product: Product) {
    this._http.post(this._baseUrl + this._addProductToShoppingCart + product.id, product, httpOptions).subscribe(x => {
      this.log(`added Product To Shopping Cart`);
      this.updateCartQuantity();
    });    
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.log(error); //log to console instead       
      this.log(`${operation} failed: ${error.message}`);
      return Observable.throw(error || 'Server error');
    };
  }
  private log(message: string) {
    console.log("Shopping Service " + message);
  }
}

One of the things, I am not liking is how api urls are hard coded as strings. This is something I want to improve upon. I will put them inside an injectable service which has all the urls.
Next thing I want to learn is authentication and authorization with ASP.NET Core.