2016-05-29 19 views
0

Ich habe eine externe API, die eine Liste zurückgibt. Ich habe folgend in ServiceNativescript: Angular2 ListView nicht aktualisiert, während Observable

load() { 
    let headers = new Headers(); 
    headers.append("Authorization", Config.token); 

    return this._http.get(Config.apiUrl + "grocery/list", {headers: headers}) 
     .map(res => res.json()) 
     .map(data => { 
      let groceryList = []; 
      data.list.forEach((grocery) => { 
       groceryList.push(new Grocery(grocery._id, grocery.name)); 
      }); 
      return groceryList; 
     }) 
     .catch(this.handleErrors); 
} 

Ich habe den folgenden Code in der Komponente:

ngOnInit() { 
    this._groceryService.load() 
     .subscribe(loadedGroceries => { 
      loadedGroceries.forEach((groceryObject) => { 
       console.dir(groceryObject); 
       this.groceryItems.unshift(groceryObject); 
      }); 
     }); 

    // It works if I uncomment this. It will just render one item, still nothing from API 
    // this.groceryItems.unshift(new Grocery('iuiu', 'jjjjj')); 
} 

Wenn ich die letzte Zeile Kommentar- darüber auf den ListView rendert. Mein ListView ist Templat entfernt und sehen aus wie folgt:

<GridLayout> 
    <ListView [items]="groceryItems" class="small-spacing"> 
    <template let-item="item"> 
     <Label [text]="item.name" class="medium-spacing"></Label> 
    </template> 
    </ListView> 
</GridLayout> 

Die API gibt so etwas wie dieses:

{ 
    "success": true, 
    "msg": "Lists found!", 
    "list": [ 
    { 
     "_id": "574a324a18cadad00665a7f3", 
     "name": "Carrot", 
     "userid": "57482f309ae6c358703066ca", 
     "completed": 0, 
     "__v": 0 
    } 
    ] 
} 
+1

Hey Deepak, ich bin mir nicht sicher was genau Geht hier falsch, aber ich habe diese Art von Problem auch getroffen. Vielleicht möchten Sie den Wechsel zu einem RxJS Observable für Ihre Liste sowie die asynchrone Pipe in Betracht ziehen. Das scheint nur die Art zu sein, wie Angular diese Art von Dingen implementieren will, und ich hatte mehr Glück mit dieser Herangehensweise. Der "eckige" Zweig des "Groceries Repo" hat eine Beispiel-Implementierung, die Sie sich https://github.com/NativeScript/sample-Groceries/tree/angular ansehen können. –

Antwort

1

nur einen Hauch

map anstelle von forEach() und push() sollten das gleiche tun, aber prägnanter:

load() { 
    let headers = new Headers(); 
    headers.append("Authorization", Config.token); 

    return this._http.get(Config.apiUrl + "grocery/list", {headers: headers}) 
     .map(res => res.json()) 
     .map(data => 
      data.list.map(grocery => new Grocery(grocery._id, grocery.name)) 
     ) 
     .catch(this.handleErrors); 
} 
2

Sie können diese Zeile hinzufügen, nachdem Sie die Load-Methode setTimeout(() => {this.cd.markForCheck();}, 0); nennen. Dadurch kann ListView jedes Mal aktualisiert werden, wenn Sie ein neues Element in das Array schieben. Ich füge hier einige Code-Schnipsel:

import {Component, Input, ChangeDetectionStrategy, ChangeDetectorRef} from "@angular/core"; import {Http, Headers, Response, ResponseOptions, HTTP_PROVIDERS} from "@angular/http"; import {Observable, BehaviorSubject} from "rxjs/Rx";

constructor(private _http: Http, private cd: ChangeDetectorRef){ 

     this.groceryItems=[]; 
    } 



ngOnInit() { 
     this.groceryItems.push(new Grocery('3','test', false, false)); 
     this.load() 
      .subscribe(loadedGroceries => { 
       loadedGroceries.forEach((groceryObject) => { 
        this.groceryItems.push(new Grocery('3',groceryObject.name, false, false)); 
        console.log(this.groceryItems.length); 
        console.log(groceryObject.name); 
       }); 
       this.cd.markForCheck(); 
      }); 
    } 
+0

Warum ist 'setTimeout()' für den Aufruf von 'cd.markForCheck()' notwendig? –

+0

'this.cd.markForCheck()' wird bereits über Änderungen benachrichtigt. 'setTimeout()' selbst benachrichtigt auch über Änderungen. Dies scheint redundant zu sein, insbesondere mit der Standard 'ChangeDetectionStrategy'. –

+0

Sie haben Recht. Ich habe meine Projekte erneut getestet und es sieht so aus, dass 'this.cd.markForCheck()' ohne 'setTimeout() 'korrekt funktioniert. –

Verwandte Themen