Reputation: 173
How can I save the result of an HTTP request from JSON format to an object in TypeScript.
Here is my code:
Component:
import { Component } from '@angular/core';
import { DateTimeService } from './datetime.service';
import { DateTime } from './datetime'
@Component({
selector: 'my-app',
moduleId: module.id,
templateUrl: 'app.component.html',
providers: [DateTimeService]
})
export class AppComponent {
constructor(private _dateTimeService: DateTimeService){ }
dateTime: DateTime = new DateTime();
getDateTime() {
this._dateTimeService.getDateTime().subscribe(data => this.dateTime = data,
error => alert("error"),
() => alert("done"));
debugger;
alert(this.dateTime.date);
alert(this.dateTime.milliseconds_since_epoch);
alert(this.dateTime.time);
}
}
Service:
import { Http } from '@angular/http';
import {Injectable} from'@angular/core';
import 'rxjs/add/operator/map'
import { DateTime } from './datetime'
@Injectable()
export class DateTimeService{
constructor(private _http: Http) { }
getDateTime() {
return this._http.get('http://date.jsontest.com').map(res => <DateTime>res.json());
}
}
All properties of DateTime
object are undefined when I run this code. However if I don't cast the incoming data to be of type DateTime
in my service, and use JSON.stringify(data.time)
(for example), I'm able only to get a single property.
Upvotes: 0
Views: 87
Reputation: 73367
All your alerts are undefined, because the alerts are run before data has been retrieved.
getDateTime() {
this._dateTimeService.getDateTime().subscribe(data => this.dateTime =
// executed sometimes later
data,
error => alert("error"),
() => alert("done"));
debugger;
// executed first
alert(this.dateTime.date);
alert(this.dateTime.milliseconds_since_epoch);
alert(this.dateTime.time);
}
If you add your alerts inside the subscription, your alerts should work
getDateTime() {
this._dateTimeService.getDateTime().subscribe(data => {
this.dateTime = data;
alert(this.dateTime.date);
alert(this.dateTime.milliseconds_since_epoch);
alert(this.dateTime.time);
});
}
This is because this is asynchronous call, so code is not executed in the order they are written. If you have trouble seeing your data in your view, this is for the same reason, view is rendered before data has been retrieved, so here comes the use of safe navigation operator or *ngIf
.
You'll have to get used to this, since we are constantly dealing with async operations ;)
So you can wrap your template inside a *ngIf
like so:
<div *ngIf="dateTime">
<!-- Your code here -->
</div>
which removes the div from the template until there is values in dateTime
(we assume there will be).
The other option is the aforementioned safe navigation operator, which you could use like so:
{{dateTime?.date}}
{{dateTime?.milliseconds_since_epoch}}
{{dateTime?.time}}
Upvotes: 2