Sunday, 7 March 2021

Angular Pipes

March 07, 2021 0
angular pipes "|"

This article covers following topics in details:

  • Purpose of having pipes in Angular.
  • Built in Pipes and its usage.
  • How to create custom Pipes

Purpose of having pipes in Angular.

Pipes are used to format your data based on the requirement. Pipes donate from symbol “|” and you can use it inside the HTML template where you display the data with interpolation.

Example if you want to format amount bases on some currency type you can use below expression.

{{ amount | currency:'EUR' }}

Pipes is simply a function which accept an input values such as integers, strings, arrays, and date and returns the transform value and display the same in the browser.

Built in Pipes and its usage.

There are several built in pipes in Angular.

  1. Uppercase pipe
  2. Lowercase pipe
  3. Date pipe
  4. Currency pipe
  5. Percent pipe
  6. Decimal pipe
  7. Slice pipe

After setting up the environment and creating the example app we will try out each default pipe provided by Angular framework.


Setting up the environment. 


I will create a new project AngularPipes. After setting up your environment please run the below command in your command prompt.

ng new angular-pipes

This will create the new project with all the necessary default libraries and files.

Now go inside the angular-pipe folder and run ng serve to up and run your application with default settings. Type http://localhost:4200/ in your browser to see the app is running.

Go to app.component.ts and type below codes. Here I have defined set of variables and assigned values to use in template file to show the usage of pipes.

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-pipes';
  todayNumber: number = Date.now();
  todayDate : Date = new Date();
  todayString : string = new Date().toDateString();
  todayISOString : string = new Date().toISOString();
  amount = 1000;
  floatValues = 2.5;
  number1 = 13.456789;
  week=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
  arrayToTranform = [1000,1500,5000];
}
Now let us see how we can use each default pipes. Type below codes in app.component.html file and see the output in a browser.

1. Uppercase Pipe
<h1>UPPERCASE</h1>
  <h2>
   Welcome to {{ title|uppercase }}
 </h2>
angular uppercase pipe example
2. Lowercase Pipe
<h1>LOWERCASE</h1>
  <h2>
    Welcome to {{ title|lowercase }}
 </h2>


angular lowercase pipe example
3. Date pipe

Below example will show you how you can use default date pipe for different formats of date values and its output.

<h1>datepipe for milisecond value: {{todayNumber}}</h1>
  <h2>
    {{todayNumber | date}}
  </h2>

  <h1>datepipe for date Object: {{todayDate}}</h1>
  <h2>
    {{todayDate | date}}
  </h2>

  <h1>datepipe for date String: {{todayString}}</h1>
  <h2>
    {{todayString | date}}
  </h2>
  
  <h1>datepipe for ISO date String: {{todayISOString}}</h1>
  <h2>
    {{todayISOString | date}}
  </h2>
angular date pipe example

All types of datetime values displays the date in ‘MMM d, yyyy’ format which is default Angular date format ‘mediumDate

To change the datetime format in angular we must pass date time format parameter to the angular pipe.
There are 12 predefined date types in Angular. We must pass first parameter “format” as quoted string with the predefined date format names listed below.

Example: 

{{todayDate | date :'short'}}

Below are the 12 formats that you can pass along with the date pipe to show date values in various ways.

short
medium
long
full
shortDate
mediumDate
longDate
fullDate
shortTime
mediumTime
longTime
fullTime

4. Currency pipe

Below example will show how you can use angular currency pipe based on locale. If you do not pass the locale default value taken as USD.

<h1>Amount {{amount}} in USD format</h1>
   <h2>
     {{amount | currency}}
   </h2>

<h1>Amount {{amount}} in Japanese yen format</h1>

   <h2>
    {{ amount | currency:'JPY' }}
   </h2>
angular currency pipe example
5. Percent pipe

Percent pipe is used to format the number based on the percentage. As an example, let us see how below code is working.

<h1>Amount {{floatValues}} as a percentage</h1>
      <h2>
        {{floatValues | percent}}
       </h2>

    <h1>Amount {{floatValues}} as a percentage</h1>
      <h2>
        {{floatValues | percent:'2.2-5'}}
      </h2>
{{floatValues | percent:'2.2-5'}}

Above syntax means you are going to represent number in a format as below.
minIntegerDigits = 2
minFractionDigits = 2
maxFractionDigits = 5

Default format for percent pipe is as below. 
minIntegerDigits = 1
minFractionDigits = 0
maxFractionDigits = 3

angular percent pipe example

6. Decimal pipe

DecimalPipe is used to format a number as decimal number. It uses number keyword with pipe operator.

<h1>Amount {{number1}} as a decimal value</h1>
      <h2>
        {{number1 | number}}
       </h2>

    <h1>Amount {{number1}} as a decimal value</h1>
      <h2>
        {{number1 | number:'2.2-5'}}
      </h2>
{{number1 | number:'2.2-5'}}

Above syntax means you are going to represent number in a format as below.
minIntegerDigits = 2
minFractionDigits = 2
maxFractionDigits = 5

Default format for decimal pipe is as below. 
minIntegerDigits = 1
minFractionDigits = 0
maxFractionDigits = 3
angular decimal pipe example
7. Slice pipe

Slice pipe is used to slice your array when you are displaying data. For an example in my app.component.ts file  has an array named week. If I wanted to show only first three day of the week, I can use slice pipe.

week=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
<h1>All days in a week</h1>
    <div *ngFor="let day of week">
      {{day}}
    </div>

    <h1>First 3 day in a week</h1>
    <div *ngFor="let day of week|slice:0:3">
      {{day}}
    </div>
angular slice pipe example

Creating a custom Pipe

So far, we have studied different kind of angular built-in pipes that we can used to format our data based on the requirement. Now we will look in to how you can write your own custom pipe. If the built-in pipes in angular does not fit for your requirement you can create your own pipe. 

As an example, let us say I wanted transform integer numbers as below.

1000 -> 1k
1500 -> 1.5k
5000 -> 5k

Let us see how you can achieve this using your own custom pipe.

In my project folder I have create the new folder called pipe and I created the new .ts file named as formatNumber.

creating a custom pipe formatnumber_ts

Below code represent my code in the formatNumber.ts file.  To create Pipe you must import module Pipe from angular/core library.

import { Pipe } from '@angular/core';

@Pipe({
  name: 'format-number'
})
export class FormatNumberPipe{
    
}
After creating a pipe class you must declare it inside the app.module.ts file as below to use this new pipe in your application.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormatNumberPipe } from './pipe/formatNumber';

@NgModule({
  declarations: [
    AppComponent,
    FormatNumberPipe
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
To implement the custom pipe functionality you need to use @Pipe decorator and must implement the interface “PipeTransform” and override the method “transform()” as below.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'formatNumber'
})
export class FormatNumberPipe implements PipeTransform{
    transform(n: number) : string {
        return (n /1000)+"K";
    }
}
In above code I have read the input number “n” and I have implemented the logic to return the output as per my requirement.

In my app.component.ts file has below array. Let us see what would be the out put after I apply my custom pipe to the values in the array.

arrayToTranform = [1000,1500,5000];

<h1>Before applying custom pipe</h1>
      <div *ngFor = "let number of arrayToTranform "> 
          {{number}}
      </div>

  <h1>After applying custom pipe</h1>
      <div *ngFor = "let number of arrayToTranform"> 
          {{number | formatNumber}}
      </div>
before and after apply angular custom pipe

Congratulations! You have successfully applied your custom pipes to format the numbers to match with your requirement. Once you go through this article you should be able to understand Angular built-in pipes and what is the purpose of having them and how you are going to use them.  Secondly you will be able to create your own pipe simply to transform the data based on the requirement. 

We will meet in another useful article like this sooner. GOOD LUCK 😊

Saturday, 23 January 2021

How to use Angular HttpClient and RxJS to consume REST API

January 23, 2021 0
Angular HttpClient and RxJS


Today I am going to discuss how you can interact with REST API services to load and manage data. 

Prerequisites

Before getting started, you need to have the below software installed on your development machine:

Node.js and npm. You can install both of them from the Node.js

Angular CLI  (You can install it from npm using: npm install -g @angular/cli)


Frontend applications needs to call backend services over http/https protocol to manage dynamic data. Best place to access data from backend APIs are service component. Once you defined your service class you can inject it in to component or another service to use the service methods. 

Angular Related Articles:

Angular provides the HttpClient service class in @angular/common/http module to interact with backend REST API services.

Using HttpClient request call you can easily handle your response and you can intercept your request and response. By intercepting the request, you can inject your security token or any other requested headers to all the service inside the one place. By intercepting the response, you can handle all the errors in a single place. I will explain interceptor concept in another chapter with more details. 

Today we will check how you can use HttpClient methods to do get data from service API. Get method of HTTP Client returns RxJS observable type and you can subscribe to the RxJS observable inside the component where you call the service method.

If you look at my flower store code in GitHub, you can see I have hard coded flower objects and put them into an array as below. 


  mySellingFlowers(){
    let rose = new flower();
    rose.name = "Rose";
    rose.price = 100;
    rose.availableQuantity = 1000;
    rose.isChecked = false;
    this. myFlowerList.push(rose);

    let lily = new flower();
    lily.name = "Lilly";
    lily.price = 80;
    lily.availableQuantity = 2000;
    lily.isChecked = false;
    this. myFlowerList.push(lily);

    let tulip = new flower();
    tulip.name = "Tulip";
    tulip.price = 100;
    tulip.availableQuantity = 2300;
    lily.isChecked = false;

    this. myFlowerList.push(tulip);

    let carnation = new flower();
    carnation.name = "Carnation";
    carnation.price = 50;
    carnation.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(carnation);

    let gerbera = new flower();
    gerbera.name = "Gerbera";
    gerbera.price = 50;
    gerbera.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(gerbera);

    let orchid = new flower();
    orchid.name = "Orchid";
    orchid.price = 50;
    orchid.availableQuantity = 1500;
    lily.isChecked = false;

    this. myFlowerList.push(orchid);

  }
  
Today we will check how you can read flowers from backend REST API call. I am planning to use designer.mocky.io to mock my API call. To access list of flowers through API and to read it from Angular side that API should return an JOSN array. Therefor I will make a JSON array to define a response in my mock API as below.

{"flowers":[  
    {"name":"Rose", "price":"100", "availableQuantity":"1000","isChecked":false},    
    {"name":"Lilly", "price":"80", "availableQuantity":"2000","isChecked":false},  		
    {"name":"Tulip", "price":"100", "availableQuantity":"2300","isChecked":false},  	   
    {"name":"Carnation", "price":"80", "availableQuantity":"1500","isChecked":false}, 
    {"name":"Gerbera", "price":"50", "availableQuantity":"1500","isChecked":false},   
    {"name":"Orchid", "price":"200", "availableQuantity":"1500","isChecked":false}   
]
}
]}

https://designer.mocky.io/ to mock my API call

Click on the generate my http response button to get the access URL. In my case it is as below.

Click on the generate my http response button to get the access run.mocky.io/v3

Now let us see how you can access this URL and display data in html. As I said earlier best place to access the data layer is service class.

To generate the service, please run below CLI command in your command prompt. 

ng g s flower
ng g s flower command

Above command generate the default flower service as below.


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class FlowerService {

  constructor() { }
}

  
The @Injectable() decorator specifies that Angular can use this class with the Dependency Injection.

The metadata, providedIn: 'root', means that the FlowerService is visible throughout the application.
Now we will write a new method in a FlowerService class to access our API end point.

The HttpClient service in Angular 4.3+ is the successor to Angular 2's Http service. Instead of returning a Promise, its http.get() method returns an RxJS Observable object.

Therefore, to call our get API method I will import the HttpClient from Angualr/common/http and Observable module from RxJS. and then injected that to our service class as below.


import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class FlowerService {

  constructor(private http:HttpClient) {}

    getFlowerList():Observable<any>{
      return this.http.get('https://run.mocky.io/v3/cee1c6e9-1491-4191-9054-ce7df1c1a500');
   }
}

  
getFlowerLIst() methods returns RxJS observable type and later in the landing component you can subscribe to access data.

To consume getFlowerList() method in our landing component we need to inject our service in to landing component through constructor and need to subscribe to the method.


constructor(private flowerService:FlowerService) { }
I have commented out my array with hard coded data and add the below codes to read data from service method.


this.flowerService.getFlowerList().subscribe(response=>{
      this.myFlowerList = response.flowers
    },
    err => console.error(err),
    () => console.log('done loading foods')
   )
I have added full code for landing component for you to refer. 


import { Component, EventEmitter, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { flower } from '../../domain/flower';
import { DataService } from 'src/app/services/data.service';
import { FlowerService } from 'src/app/services/flower.service';

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

  myFlowerList:flower[]=[];
  selectedFlowers: string[] =[];

  checkedList:string[]=[];
  searchText:string='';
  constructor(private dataService:DataService, private flowerService:FlowerService) { }

  ngOnInit() {
    this.mySellingFlowers();
    this.dataService.getSearchText().subscribe(response => {
      this.printSearchtext(response);
    })
  }

  printSearchtext(searchText){
    this.searchText = searchText;
  }

  printOrder(flowerName){
    if(this.selectedFlowers.indexOf(flowerName)<0){
      this.selectedFlowers.push(flowerName)
    }
    else{
      let index = this.selectedFlowers.indexOf(flowerName);
      this.selectedFlowers.splice(index,1);
    }

  }

  mySellingFlowers(){
    // let rose = new flower();
    // rose.name = "Rose";
    // rose.price = 100;
    // rose.availableQuantity = 1000;
    // rose.isChecked = false;
    // this. myFlowerList.push(rose);

    // let lily = new flower();
    // lily.name = "Lilly";
    // lily.price = 80;
    // lily.availableQuantity = 2000;
    // lily.isChecked = false;
    // this. myFlowerList.push(lily);

    // let tulip = new flower();
    // tulip.name = "Tulip";
    // tulip.price = 100;
    // tulip.availableQuantity = 2300;
    // lily.isChecked = false;

    // this. myFlowerList.push(tulip);

    // let carnation = new flower();
    // carnation.name = "Carnation";
    // carnation.price = 50;
    // carnation.availableQuantity = 1500;
    // lily.isChecked = false;

    // this. myFlowerList.push(carnation);

    // let gerbera = new flower();
    // gerbera.name = "Gerbera";
    // gerbera.price = 50;
    // gerbera.availableQuantity = 1500;
    // lily.isChecked = false;

    // this. myFlowerList.push(gerbera);

    // let orchid = new flower();
    // orchid.name = "Orchid";
    // orchid.price = 50;
    // orchid.availableQuantity = 1500;
    // lily.isChecked = false;

    // this. myFlowerList.push(orchid);

    this.flowerService.getFlowerList().subscribe(response=>{
      this.myFlowerList = response.flowers
    },
    err => console.error(err),
    () => console.log('done loading foods')
   )

  }

  trackFlowers(index,flower){
    return flower?flower.name:undefined
  }
}

  
The subscribe() method takes three arguments which are event handlers. They are called onNext, onError, and onCompleted. 

The onNext method will receive the HTTP response data

The onError event handler is called if the HTTP request returns an error code such as a 500. 

The onCompleted event handler executes after the Observable has finished returning all its data. 

myFlowerList array contains data return from the API call and using *ngFor you can iterate and display it in a HTML as below.


<div *ngFor="let flower of myFlowerList;trackBy:trackFlowers">
      <flower-card [title]="flower.name" (selectedFlower)="printOrder($event)"></flower-card>
</div>
To use the Angular HttpClient, we need to inject it into our app's dependencies in app.module.ts file as below.


imports: [
    BrowserModule,
    AppRoutingModule,
    CardModule,
    CheckboxModule,
    CommonModule,
    FormsModule,
    InputTextModule,
    HttpClientModule
    ],
Unless it gives you below error.

core.js:7187 ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[HttpClient]: 
  StaticInjectorError(Platform: core)[HttpClient]: 
    NullInjectorError: No provider for HttpClient!
NullInjectorError: StaticInjectorError(AppModule)[HttpClient]:
I have added app.module.ts file code after adding the dependency and you can check full code to the app by accessing GitHub.


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LandingComponent } from './modules/landing/landing.component';
import { HomeComponent } from './modules/home/home.component';
import { CardModule } from 'primeng/card';
import {CheckboxModule} from 'primeng/checkbox';
import { CommonModule } from '@angular/common';
import { FormsModule }    from '@angular/forms';
import {InputTextModule} from 'primeng/inputtext';
import { FlowerCardComponent } from './modules/cards/flower-card/flower-card.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    LandingComponent,
    HomeComponent,
    FlowerCardComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    CardModule,
    CheckboxModule,
    CommonModule,
    FormsModule,
    InputTextModule,
    HttpClientModule
    
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Once you load the app it will show same data as before by getting the data from backend API call.

My Flower Store Angular App

Conclusion

In this tutorial, we used HttpClient and RxJS modules to retrieves data from a REST API using the get() method of HttpClient. First I have explained how you can generate service component using the CLI command. Then I have described how  to subscribe to the RxJS Observable returned by the get() method and how to use the *ngFor directive to iterate over fetched data in the template.