I’m writing my first Ionic 2 app and am struggling to get my head around something that I didn’t have to worry about in Ionic 1.
I have a list view which lists items fetched from an API via an ajax call. This works fine, the template doesn’t break whilst waiting for the data to load. But and here is my issue, when you click on an item in the list view, you go to a detail view (which makes another ajax call to fetch additional details). This view renders before the ajax call has completed, all the template vars error and I’m really not sure why.
Here’s my Service which handles the ajax calls:
import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/Rx';
@Injectable()
export class DataService {
http: any;
baseUrl: String;
apiKey: String;
constructor(http:Http) {
this.http = http;
this.baseUrl = 'http://localhost:8100/api';
this.apiKey = 'xxx';
}
getList(token, page) {
return this.http.get(this.baseUrl + '/list?key=' + this.apiKey + '&token=' + token + '&page=' + page + '&per_page=20')
.map(res => res.json());
}
getDetails(token, ref) {
return this.http.get(this.baseUrl + '/details/' + ref + '?key=' + this.apiKey + '&token=' + token)
.map(res => res.json());
}
}
1st page (list) which contains the nav push to the details page (this all works fine):
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Storage } from '@ionic/storage';
import { DataService } from '../../app/services/data.service';
import { ItemPage } from '../item/item';
@Component({
templateUrl: 'list.html'
})
export class ListPage {
token: string;
page: number = 1;
items: any;
constructor(public navCtrl: NavController, private dataService:DataService, private storage: Storage) {
}
getItems(token, page) {
this.dataService.getItemsByFilter(token, page).subscribe(
data => {
this.items = data.items;
},
err => {
console.log(err);
// handle expired token and redirect
}
);
}
ngOnInit() {
this.storage.get('token').then((val) => {
this.token = val;
this.getItems(this.token, this.page);
});
}
viewDetailsPage(ref) {
// I could perform the second ajax call (to get the details) within this function but this doesn't feel right...
this.navCtrl.push(ItemPage, {
ref: ref
})
}
}
2nd page (details) which has the issue:
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Storage } from '@ionic/storage';
import { DataService } from '../../app/services/data.service';
@Component({
selector: 'details',
templateUrl: 'details.html'
})
export class DetailsPage {
token: string;
item: any;
ref: string;
constructor(public navCtrl: NavController, private dataService:DataService, private storage: Storage, public params:NavParams) {
this.ref = params.get('ref');
}
getDetail(token, ref) {
this.dataService.getDetails(token, ref).subscribe(
data => {
// this completes after the view has rendered, so the view errors
this.item = data;
console.log('this.item = ');
console.log(this.item);
},
err => {
console.log(err);
// handle expired token and redirect
}
);
}
ngOnInit() {
console.log('on init ran...');
this.storage.get('token').then((val) => {
this.token = val;
this.getDetail(this.token, this.ref);
});
}
}
Every var in my template errors, for example, the first is:
> Runtime Error
> Cannot read property 'reference' of undefined
Am I missing something obvious or is there a better way to go about this? All the tutorials I find have the ajax call in the class and not in a service which can't be right...
Here’s the list page template:
<ion-header>
<ion-navbar>
<ion-title>Items</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<button ion-item *ngFor="let item of items" (click)="viewDetailsPage(item.reference)" icon-start>
<h2>{{item.reference}}</h2>
<p>{{item.type.title}}</p>
<ion-badge item-end>{{item.status.title}}</ion-badge>
</button>
</ion-list>
</ion-content>
and the details page template:
<ion-header>
<ion-navbar>
<ion-title>Item</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<h4>{{item.reference}}</h4>
</ion-content>
what am I missing, why is the second (details) template erroring?