Nativescript:Angular2 ListView 在使用可观察对象时不更新

Nativescript: Angular2 ListView not updating while using observables

我有一个 API 的外部 returns 列表。我有以下服务

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

我在组件中有以下代码:

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

如果我取消注释上面的最后一行,它会在 ListView 上呈现。我的 ListView 已模板化,如下所示:

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

API returns 是这样的:

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

您可以在调用加载方法后添加此行setTimeout(() => {this.cd.markForCheck();}, 0);。这将允许每次将新项目推送到数组时更新 ListView。我在下面附上一些代码片段:

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

一点提示

使用 map 而不是 forEach()push() 应该做同样但更简洁:

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