Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Date deserialization

Tags:

I have an Angular 2 application. A service is requests data from an api that returns the results like the following:

{     "data":[         {"id":1,"timestamp":"2016-04-17T19:52:53.4510935+01:00","sourceDatabaseServer":"127.0.0.1","sourceDatabaseName":"Database1","targetDatabaseServer":"192.168.99.101","targetDatabaseName":"Database2"},         {"id":2,"timestamp":"2016-04-17T19:52:53.4510935+01:00","sourceDatabaseServer":"127.0.0.2","sourceDatabaseName":"Database3","targetDatabaseServer":"192.168.99.102","targetDatabaseName":"Database4"},         {"id":3,"timestamp":"2016-04-17T19:52:53.4510935+01:00","sourceDatabaseServer":"127.0.0.3","sourceDatabaseName":"Database5","targetDatabaseServer":"192.168.99.103","targetDatabaseName":"Database6"}     ] } 

My Angular 2 service looks like this (I've cut the error handling for brevity as we're on the happy path here):

getList() : Observable<SomeModel[]> {     return this._http.get(this._getListUrl).map(this.extractData); }   private extractData(res: Response) {     return res.json().data || {}; } 

and my component like this:

results: SomeModel[]; errorMessage: string; ngOnInit() {     this._someService.getList()         .subscribe(         results => this.results = results,          error => this.errorMessage = <any>error); } 

and my model like this:

export class SomeModel {      constructor(         public id: number,         public timestamp: Date,         public sourceDatabaseServer: string,         public sourceDatabaseName: string,         public targetDatabaseServer: string,         public targetDatabaseName: string     ) { } } 

Everything looked like it was working however when I tried to display timestamp using the DatePipe like so {{item.timestamp | date:'short'}} the application blows up with the following error message:

Invalid argument '2016-04-17T19:40:38.2424240+01:00' for pipe 'DatePipe' in [{{result.timestamp | date:'short'}} 

After some investigation I believe that timestamp is not actually being converted to the Date type but is instead just being set a string. I'm guessing this is becuase the Date type isn't known at the time Response.json() is called? or am I missing something else entirely? Is there a fix or work around for this?

like image 847
rcarrington Avatar asked Apr 17 '16 19:04

rcarrington


2 Answers

I would map the string field to a date one:

getList() : Observable<SomeModel[]> {   return this._http.get(this._getListUrl).map(this.extractData); }  private extractData(res: Response) {   var data = res.json().data || [];   data.forEach((d) => {     d.timestamp = new Date(d.timestamp);   });   return data; } 
like image 192
Thierry Templier Avatar answered Oct 21 '22 06:10

Thierry Templier


The date pipe only accepts Date values not string values.

See How to get Date object from json Response in typescript for how to convert dates in JSON.

Alternatively you can create your own string-to-date conversion pipe

@Pipe({name: 'toDate'}) export class StringToDate implements PipeTransform {   transform(value, [exponent]) : number {     if(value) {       return new Date(value);     }   } } 

and then use it like

{{item.timestamp |toDate | date:'short'}} 

Hint: don't forget to add the pipe to pipes: [StringToDate] on the @Component(...) decorater where you want to use it.

See also

  • https://github.com/angular/angular/pull/8038
  • https://github.com/angular/angular/pull/7794
like image 34
Günter Zöchbauer Avatar answered Oct 21 '22 07:10

Günter Zöchbauer