Date Handling in Angular Application (Part 2 — Angular Http Client Interceptor / Rxjs Pipe Map)

Ben Cheng
3 min readJul 2, 2019

--

Introduction

The below is a summary of previous article about JavaScript Date Object and JSON Date.

  • JSON is common communication format between server side and client side
  • JavaScript Date Object is Time zone and Locale Dependent
  • ISO 8601 Date Format is a general agreement for JSON Date representation
  • JavaScript do not know JSON date type. Conversion between JSON Date String and JavaScript Date Object is required.

Seamless Integration Approaches

In Angular Application, what could be done in order to make the seamless integration of JavaScript Date Object, JSON and UI Components?

There would be two parts for seamless integration.

  • Communication between Client Side and Server Side

Communication between Client Side and Server Side

In Angular Application, it would provide HttpClientModule for simplifying HTTP Communication between client side and server side.

this.httpClient.get<DataModel>("/api/getData").subscribe(
(data: DataModel) => {
console.log(data);
}
);

Although, the data model (interface) is defined above, JSON does not define date object. The date object would be presented as Data String in ISO format. The Data String would simply assign to date even though it is defined as Date in Interface in TypeScript.Note that the interface would be compiled to nothing and it is only for tying checking in typescript context.

interface DataModel {
data1: string;
data2: string;
data3: string
date1: Date;
date2: Date;
date3: Date
}

There would be two approaches to convert

  • Http Client Pipe
  • Angular Http Interceptor

Http Client Pipe

Http Client would return Observable for various provided method. The map operator in pipe could be used to convert date string to date object.

this.httpClient.get<DataModel>("/api/getData")
.pipe(
map((data)=>{
data.date1 = new Date(data.date1);
data.date2 = new Date(data.date2);
data.date3 = new Date(data.date3);
return data;
})
).subscribe(
(data: DataModel) => {
console.log(data);
}
);

Angular Http Interceptor

As the date string is in ISO 8601, we want to have a generic way to do all the conversion. A custom HttpInterceptor would be added to Angular Application for intercepting request and response.

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export class JsonDateInterceptor implements HttpInterceptor { private _isoDateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d*)?Z$/;

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(map( (val: HttpEvent<any>) => {
if (val instanceof HttpResponse){
const body = val.body;
this.convert(body);
}
return val;
}));
}
isIsoDateString(value: any): boolean {
if (value === null || value === undefined) {
return false;
}
if (typeof value === 'string'){
return this._isoDateFormat.test(value);
} return false;
}
convert(body: any){
if (body === null || body === undefined ) {
return body;
}
if (typeof body !== 'object' ){
return body;
}
for (const key of Object.keys(body)) {
const value = body[key];
if (this.isIsoDateString(value)) {
body[key] = new Date(value);
} else if (typeof value === 'object') {
this.convert(value);
}
}
}
}
this._httpClient.post<Value>("/api/posts", this.value)  
.subscribe((val: Value) => {
console.log(val.date1);
});

Reference

--

--

Ben Cheng

A developer in Hong Kong. Learning and rethinking as a developer. Welcome to contact me and make friend with me. Cooperation is welcome.