2016-06-27 12 views
0

Ich lerne Ionic-2-App zu bauen, habe ich ein paar Komponenten, die Dienste, die einen http-Aufruf und holen einige Daten, die wiederum in der Komponente eingestellt werden und werden schließlich verbrauchen in der Vorlage angezeigt werden. Ich habe den Fluss insgesamt verstanden, aber beim Codieren mache ich einen logischen Fehler.Ionic2/angular2 korrekte Art der konsumierenden Service

Mein Beispiel Komponente:

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 
    }) 

    } 
} 

Mein entsprechenden 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; 

     } 
} 

Screenshot der App: enter image description here

So ist das Problem hier ist:

  • Wenn ich klicken Fetch-Taste (die Anrufe getData() Funktion in der Komponente) wird es die Daten nicht geladen werden, irgendwie in dem Konstruktor der Komponente der Daten festgelegt werden muss und nicht wenn ich getData() Funktion aufrufen. Ich habe versucht, this.items = this.testService.fetchData() diese Zeile im Konstruktor schreiben, aber es funktioniert nicht.

  • Dieses Problem wird weiter verschlechtert, wenn sie in einer anderen Komponente und Service Ich habe navparam von diesem FarmList Komponente beifügt: let myUrl = 'http://jsonplaceholder.typicode.com/users/' + this.id ; Ich versuche this.id anhängen, die zu empfangen navparam darin Konstruktor gesetzt ist und ich erhalten undefined

    Konstruktor (privat nextService: nextService, navParams: NavParams) { this.id = navParams.get ("param1"); }

Ich versuche einfach nur auf einer Seite eine Liste zu haben und dann auf einen der Listeneinträge klicken, werden neue Seite öffnen damit einige weitere Details ist. Ich treffe diese öffentlich verfügbare API: http://jsonplaceholder.typicode.com/users/ und dann eine Nummer an sie anhängen, um nur ein Objekt zu erhalten.

Was ist der richtige Weg?

UPDATE: ich das zweite Problem, indem sie einfach immer navParams in Service Konstruktor lösen könnte und es an die URL angehängt wird, wie folgt:

@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 ; 
... 
} 
+0

Haben Sie versucht, mit Hilfe von [ngOninit] (https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html)? –

+0

Nein, ich wusste nichts davon. Irgendwelche Anweisungen, wie man es benutzt? – Nitish

Antwort

1

ngOnInit könnte sein, was Sie suchen:

import { OnInit} from '@angular/core'; 
... 
export class FarmList implements OnInit { 
    ... 
    ngOnInit(){ 
     this.getData() 
    } 
} 

Lesen Sie mehr bei angular

EDIT:

Aufgrund Ihrer Kommentare, die ich an einen anderen Blick nahm, was Ihre Anrufe tun.In der Komponente setzen Sie die Daten auf das, was von der fetchData-Funktion zurückgegeben wird, die nur die Daten zurückgibt, auf die im Service festgelegt wurde. Zum Zeitpunkt, zu dem ngOnInit aufgerufen wird, handelt es sich lediglich um ein leeres Objekt, und nach einigen Millisekunden wird service.data dann in das geändert, was von Ihrem http-Async-Aufruf zurückgegeben wird.

Die bessere Praxis wäre zu folgen Angular's Http getting started tutuorial. Im Grunde denke ich, mit etwas mehr wie das enden würde:

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) 
     } 
} 

Komponente:

import { OnInit} from '@angular/core'; 
... 
export class FarmList implements OnInit { 
    ... 
    ngOninit(){ 
     this.getData() 
    } 
    getData(){ 
     this.testService.fetchData().then(data => this.items = data) 
    } 
} 
+0

Wenn ich versuche, Oninit zu implementieren, gibt es einen Kompilierungsfehler, der besagt: FarmList implementiert die Schnittstelle 'Oninit' falsch. Die Eigenschaft ngOninit fehlt im Typ FarmList. Was heißt das? Ich habe genau das selbe getan wie du erwähnt und auf Docs verwiesen. – Nitish

+0

Ok das wurde gelöst: anstelle von ngOninit() musste es ngOnInit() sein, es war ein Tippfehler. Die Liste wurde jedoch nicht automatisch geladen. Ich musste trotzdem auf die Schaltfläche klicken, um getData() aufzurufen. – Nitish

+0

In diesem Fall haben Sie einige asynchrone Probleme. Ich werde die Antwort in einem Moment bearbeiten –

Verwandte Themen