Wednesday, August 26, 2020

use models in angular

In the big web application, it is very important and useful to create angular models. Sometimes after the completed website or module, we need to change some information so it's hard to change in all places without using the model, but if you had used model then it is very easy to change it.

If backend and frontend teams are separate in web development and all code has separate for both backend and frontend teams then it is very hard for check object properties used in particular modules/page without using models.

Generally, we can create models using two ways
->Using interface
->Using class

Interfaces are very useful when you only need type checking whereas classes are very useful when you not only want the type checking, but you need some methods or require some other logic.

Interfaces are only at compile time whereas class are present at runtime and you can define methods in them with processing

Here we will discuss how to use models using class in angular 2+ like as angular 7, angular 8, angular 9, etc

Here we will make a simple model for product-brand with three different Demos
1)in the first demo return  productBrand object list only in response from service
2)in second demo return  productBrand object with status and responseCode in response from service
3)in third demo return  productBrand object with status and responseCode in response from service with change id to brandId property

=>Demo 1
in Demo 1, we will learn how to use model and return only model objects only without any status code, etc.
Demo 1 is very simple to use it.

GET /api/get-brands (The API Response)
{
    "status": "success",
    "responseCode" : 200,
    "data": [
        {
            "brandId": 1,
            "brandName": "amul"
        },
        {
            "brandId": 2,
            "brandName": "tata"
        },
        {
            "brandId": 3,
            "brandName": "nutrela"
        },
        {
            "brandId": 4,
            "brandName": "fortune"
        },
    ]
}

\app\shared\models\product-brand.model.ts
import {Deserializable} from './deserializable.model';

export class ProductBrand implements Deserializable {
  public brandId: number;
  public brandName: string;

  deserialize(input: any): this {
    Object.assign(this, input); //Assign input to our object
    return this;
  }

}

\app\shared\models\deserializable.model.ts
export interface Deserializable {
    deserialize(input: any): this;
}

\app\pages\product-brand\product-brand.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { BehaviorSubject, Observable } from 'rxjs';
import { ProductBrand } from '../../shared/models/product-brand.model';
import 'rxjs/add/operator/map';
...
...
...


@Injectable({
  providedIn: "root",
})
export class ProductBrandService {
  ...
  ...
  ...

  constructor(private http: HttpClient) {}

  ...
  ...
  ...
  getBrandList(params:any): Observable<ProductBrand[]> {
    return this.http.get(this.Url+"/api/get-brands",{params : params}).map((res: any) => res.data.map((productBrand: ProductBrand) => new ProductBrand().deserialize(productBrand)));
  }
  ...
  ...
  ...

}

\app\pages\product-brand\product-brand.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { ProductBrandService} from "./product-brand.service";
import { ProductBrand } from '../../shared/models/product-brand.model';
...
...
...

@Component({
  selector: 'app-product-brand',
  templateUrl: './product-brand.component.html',
  styleUrls: ['./product-brand.component.scss']
})
export class ProductBrandComponent implements OnInit {

  public productBrands : ProductBrand[]
  constructor(public productBrandService: ProductBrandService) {
   
   }

  ngOnInit() {
      let params:any = {};
      ...
      ...
      ...

      this.productBrandService.getBrandList(params).subscribe((res: any) => {
        console.log(res);
        this.productBrands = res;
        //console.log("getBrandList obj", this.productBrands);
      },
      (error: any) => {
        ...
        ...
        ...
      }
    );
  }
  ...
  ...
  ...
}

Output (Result)
(4) [Object, Object, Object, Object]
[
    ProductBrand {brandId: 1, brandName: "amul"}
    ProductBrand {brandId: 2, brandName: "tata"}
    ProductBrand {brandId: 3, brandName: "nutrela"}
    ProductBrand {brandId: 4, brandName: "fortune"}
]

=>Demo 2
in this Demo 2, we will learn how to use a model with status code, httpResponse, totalPage for pagination etc.
Demo 2 is a biter hard than Demo 1.

GET /api/get-brands (The API Response)
{
    "status": "success",
    "responseCode" : 200,
    "data": [
        {
            "brandId": 1,
            "brandName": "amul"
        },
        {
            "brandId": 2,
            "brandName": "tata"
        },
        {
            "brandId": 3,
            "brandName": "nutrela"
        },
        {
            "brandId": 4,
            "brandName": "fortune"
        },
    ]
}

\app\shared\models\product-brand.model.ts
import {Deserializable} from './deserializable.model';

export class ProductBrand implements Deserializable {
  public brandId: number;
  public brandName: string;

  deserialize(input: any): this {
    Object.assign(this, input); //Assign input to our object
    return this;
  }

}

\app\shared\models\deserializable.model.ts
export interface Deserializable {
    deserialize(input: any): this;
}

\app\pages\product-brand\product-brand.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { BehaviorSubject, Observable } from 'rxjs';
import { ProductBrand } from '../../shared/models/product-brand.model';
import 'rxjs/add/operator/map';
...
...
...

export interface IPagedResponse<T> {
    status: string;
    responseCode: number;
    data: T[];
}

@Injectable({
  providedIn: "root",
})
export class ProductBrandService {
  ...
  ...
  ...

  pageResponse: IPagedResponse<ProductBrand>;


  constructor(private http: HttpClient) {}

  ...
  ...
  ...
  getBrandList(params:any): Observable<IPagedResponse<ProductBrand>> {
    return this.http.get(this.Url+"/api/get-brands",{params : params}).map((res: any) => {
      return {
          data: <ProductBrand[]>res.data.map((productBrand: ProductBrand) => new ProductBrand().deserialize(productBrand)),
          status: "success",
          responseCode: 200
      }
  });
  ...
  ...
  ...

}

\app\pages\product-brand\product-brand.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { ProductBrandService} from "./product-brand.service";
import { ProductBrand } from '../../shared/models/product-brand.model';
...
...
...

@Component({
  selector: 'app-product-brand',
  templateUrl: './product-brand.component.html',
  styleUrls: ['./product-brand.component.scss']
})
export class ProductBrandComponent implements OnInit {

  public productBrands : ProductBrand[]
  constructor(public productBrandService: ProductBrandService) {
   
   }

  ngOnInit() {
      let params:any = {};
      ...
      ...
      ...

      this.productBrandService.getBrandList(params).subscribe((res: any) => {
        if (res.responseCode == 200) {
          console.log(res);
          this.productBrands = res.data;
          //console.log("getBrandList obj", this.productBrands);
        }else{
          ...
          ...
          ...
        }

      },
      (error: any) => {
        ...
        ...
        ...
      }
    );
  }
  ...
  ...
  ...
}

Output (Result)
responseCode: 200,
status: "success",
data : (4) [Object, Object, Object, Object]
[
    ProductBrand {brandId: 1, brandName: "amul"}
    ProductBrand {brandId: 2, brandName: "tata"}
    ProductBrand {brandId: 3, brandName: "nutrela"}
    ProductBrand {brandId: 4, brandName: "fortune"}
]

=>Demo 3
in this Demo 3, we will learn how to use a model with status code, httpResponse, totalPage for pagination, etc with change backend property to other property in frontend.
Demo 3 is very useful when some field changes come in API after the project/module is completed, we can stay frontend side the same property without changes in all pages.
For this, we need to change only form models.

GET /api/get-brands (The API Response)
{
    "status": "success",
    "responseCode" : 200,
    "data": [
        {
            "id": 1,
            "brandName": "amul"
        },
        {
            "id": 2,
            "brandName": "tata"
        },
        {
            "id": 3,
            "brandName": "nutrela"
        },
        {
            "id": 4,
            "brandName": "fortune"
        },
    ]
}

\app\shared\models\product-brand.model.ts
import {Deserializable} from './deserializable.model';

export class ProductBrand implements Deserializable {
  public brandId: number;
  public brandName: string;

  deserialize(input: any): this {
    Object.assign(this, {brandId : input.id, brandName : input.brandName}); //Assign input to our object as per our field
    return this;
  }

}

\app\shared\models\deserializable.model.ts
export interface Deserializable {
    deserialize(input: any): this;
}

\app\pages\product-brand\product-brand.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { BehaviorSubject, Observable } from 'rxjs';
import { ProductBrand } from '../../shared/models/product-brand.model';
import 'rxjs/add/operator/map';
...
...
...

export interface IPagedResponse<T> {
    status: string;
    responseCode: number;
    data: T[];
}

@Injectable({
  providedIn: "root",
})
export class ProductBrandService {
  ...
  ...
  ...

  pageResponse: IPagedResponse<ProductBrand>;


  constructor(private http: HttpClient) {}

  ...
  ...
  ...
  getBrandList(params:any): Observable<IPagedResponse<ProductBrand>> {
    return this.http.get(this.Url+"/api/get-brands",{params : params}).map((res: any) => {
      return {
          data: <ProductBrand[]>res.data.map((productBrand: ProductBrand) => new ProductBrand().deserialize(productBrand)),
          status: "success",
          responseCode: 200
      }
  });
  ...
  ...
  ...

}

\app\pages\product-brand\product-brand.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { ProductBrandService} from "./product-brand.service";
import { ProductBrand } from '../../shared/models/product-brand.model';
...
...
...

@Component({
  selector: 'app-product-brand',
  templateUrl: './product-brand.component.html',
  styleUrls: ['./product-brand.component.scss']
})
export class ProductBrandComponent implements OnInit {

  public productBrands : ProductBrand[]
  constructor(public productBrandService: ProductBrandService) {
   
   }

  ngOnInit() {
      let params:any = {};
      ...
      ...
      ...

      this.productBrandService.getBrandList(params).subscribe((res: any) => {
        if (res.responseCode == 200) {
          console.log(res);
          this.productBrands = res.data;
          //console.log("getBrandList obj", this.productBrands);
        }else{
          ...
          ...
          ...
        }

      },
      (error: any) => {
        ...
        ...
        ...
      }
    );
  }
  ...
  ...
  ...
}

Output (Result)
responseCode: 200,
status: "success",
data : (4) [Object, Object, Object, Object]
[
    ProductBrand {brandId: 1, brandName: "amul"}
    ProductBrand {brandId: 2, brandName: "tata"}
    ProductBrand {brandId: 3, brandName: "nutrela"}
    ProductBrand {brandId: 4, brandName: "fortune"}
]

In this demo 3, the only change is available in "product-brand.model.ts" file in the following method

deserialize(input: any): this {
  Object.assign(this, {brandId : input.id, brandName : input.brandName}); //Assign input to our object as per our field
  return this;
}

From the above 3 demos, I hope now it is clear how to use models in an angular web project.

No comments:

Post a Comment