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);
}
我有一个 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);
}