Reputation: 187
I ran into a strange error in Angular 2. I have two similar components with similar templates and similar services. Here is the basics of how they work:
Component:
theData: any;
constructor(private _theService: TheService) {}
ngOnInit() {
this._theService.getData()
.subscribe(data => {
this.theData = data;
});
}
Service:
private _url = "http://url.net/api/Data";
constructor(private _http: Http) {
}
getData() {
return this._http.get(this._url)
.map(res => res.json());
}
this returns an array of objects, like:
[
{name: "Name 1"},
{name: "Name 2"}
]
and the Template displays them like:
<div *ngFor="let item of theData">{{ item.name }}</div>
Then you can click into an item where you are taken to a page that follows the same strategy as above, except the service/api only returns a single object and the template does not use *ngFor because there is only one item to show.
So it looks like:
theItem = {name: "Name 1"} // what the service returns
<div>{{ theItem.name }}</div>
Everything works great when displaying all items, but when I click into the individual items, OnInit is called twice and I get an error in platform-browser.umd.js which is really an error in the template because it says the it can't read the property name
of undefined
(which is theItem).
I solved this problem by changing the template for individual items to:
<div>{{ theItem?.name }}</div>
At first I thought the problem was that the template was rendering before the data had loaded from the service, so adding ?
fixed it. But shouldn't the template be loading AFTER ngOnInit has finished? My question is, why did adding the ?
fix this problem, even though I don't need it in the first template when loading all items?
Thanks.
Upvotes: 3
Views: 3392
Reputation: 1976
Because, the get
is asynchronous, it does in fact begin to render the template before the data is loaded. It will fire off the service call and won't wait, it will continue processing. Adding the ?
allows it to be undefined
and then render appropriately once the data is loaded.
Upvotes: 4