Reputation: 5356
I am learning to build Ionic-2 app, I have a few components which consume services that make an http call and fetch some data, which in turn will be set in component and will finally be displayed in template. I overall understood the flow but I am making some logical mistake while coding it.
My example component:
export class FarmList {
items: Object;
constructor(private testService: TestService, public nav: NavController){}
getData(): any {
this.items = this.testService.fetchData()
}
nextView(){
this.nav.push(Farm)
}
showDetails(id: Number){
this.nav.push(Farm, {
param1: id
})
}
}
My corresponding service:
@Injectable()
export class TestService{
loading: boolean;
data: Object;
constructor(private http: Http){
let myUrl = 'http://jsonplaceholder.typicode.com/users';
this.loading = true;
this.http.request(myUrl)
.subscribe(
(res: Response) => {
this.loading=false;
this.data=res.json();
});
}
public fetchData(){
return this.data;
}
}
So the problem here is:
Unless I click Fetch button (which calls getData() function in the component) it will not load the data, somehow in the constuctor of the component the data must be set and not when I call getData()
function. I tried writing this.items = this.testService.fetchData()
this line in the constructor but it doesn't work.
This problem further becomes worse when in another component and service I have to append navparam
sent from this FarmList component: let myUrl = 'http://jsonplaceholder.typicode.com/users/' + this.id ;
I try to append this.id which is set to received navparam in it's constructor and I get undefined
constructor (private nextService: NextService, navParams: NavParams){ this.id = navParams.get("param1"); }
I am simply trying to have a list on one page and then clicking on one of the list items will open new page with it's some more details. I am hitting this publically available API: http://jsonplaceholder.typicode.com/users/ and then appending some number to it to get only one object.
What is the correct way to do it?
UPDATE: I could solve the second problem by simply getting navParams in service constuctor and appending it to the url as follows:
@Injectable()
export class NextService{
loading: boolean;
data: Object;
id: Number;
constructor(private http: Http, navParams: NavParams){
this.id = navParams.get("param1");
console.log("Second service fetching param: " + this.id)
let myUrl = 'http://jsonplaceholder.typicode.com/users/' + this.id ;
...
}
Upvotes: 0
Views: 626
Reputation: 7328
ngOnInit might be what you are looking for:
import { OnInit} from '@angular/core';
...
export class FarmList implements OnInit {
...
ngOnInit(){
this.getData()
}
}
Read more at angular
EDIT:
Due to your comments I took another look at what your calls are doing. In the component you are setting the data to whatever is returned from the fetchData function which is only returning what data is set to in the service. Which at the time that ngOnInit is called is just an empty object and then a few milliseconds later service.data gets changed to whatever is returned from your http async call.
The better practice would be to follow Angular's Http getting started tutuorial. In essence I think you would end up with something more like this:
Service:
@Injectable()
export class TestService{
private myUrl: string = 'http://jsonplaceholder.typicode.com/users';
// loading: boolean;
//move any logic that has to do with UI to the component...
//this is more of a suggestion and has to do with MV* best practices
constructor(private http: Http){
// I think it was in John Papa's Pluralsight video on angular 2 that said
// try to do as little as possible inside of the constructor
}
public fetchData(){
//the key here is to return a promise (or observable) so that the
//component can handle it when it gets resolved
return this.http.get(myUrl)
.toPromise()
.then(response => response.json().data)
}
}
Component:
import { OnInit} from '@angular/core';
...
export class FarmList implements OnInit {
...
ngOninit(){
this.getData()
}
getData(){
this.testService.fetchData().then(data => this.items = data)
}
}
Upvotes: 1