当角阵更新2不更新 [英] Angular 2 not updating when array is updated
问题描述
我有通过火力获取某些对象的服务。然后它填充的阵列应该然后提示角度来更新与一个* ngFor语句DOM中,但它不工作。 code如下:
I have a service that fetches some objects via firebase. It then populates an array which should then prompt angular to update the DOM with an *ngFor statement, but it doesn't work. Code as follows:
TeachersService
import {Injectable} from 'angular2/core';
import {Teacher} from './teacher.ts';
@Injectable()
export class TeachersService {
private firebaseURL: string;
private teachersRef: Firebase;
constructor() {
this.firebaseURL = "https://xyz.firebaseio.com/teachers";
this.teachersRef = new Firebase(this.firebaseURL);
}
getTeachers() {
this.teachersRef.on("value", function(snapshot) {
var tempArr = new Array(snapshot.numChildren());
// this.teachers = snapshot.val();
snapshot.forEach(function(data) {
var teacher = {
name: data.key(),
position: data.val().stilling
}
tempArr.push(teacher);
});
// this.teachers = tempArr;
console.log(tempArr);
return Promise.resolve(tempArr);
});
return Promise.resolve([]);
}
}
和教师
import {Component, AfterViewInit, OnInit, View} from 'angular2/core';
import {NgFor} from 'angular2/common';
import {Router} from 'angular2/router';
import {TeachersService} from '../../services/teachers.service';
@Component({
selector: 'teachers',
templateUrl: './components/teachers/teachers.html',
providers: [TeachersService]
})
export class TeachersCmp implements AfterViewInit, OnInit {
private firebaseURL: string;
private teachersRef: Firebase;
public teachers: Array<any>;
constructor(
private _router: Router,
private _teachersService: TeachersService
) {}
ngOnInit() {
this.populateTeachersArr();
}
populateTeachersArr() {
this._teachersService.getTeachers().then(teachers => this.teachers = teachers);
}
}
Teachers.html
<ul>
<li *ngFor="#teacher of teachers">
<strong>{{teacher.name}}</strong>: {{teacher.position}}
</li>
我怀疑这是与变化检测(或者至少是我对它的理解)做。但我不知道如何提示NG2探测阵列更新。如果我创建了一个静态数组,如: [1,2,3,4]
的* ngFor语句中正确工作,并将其显示像它应该在DOM
I suspect this has to do with change detection (or at least my understanding of it). But I don't know how to prompt ng2 to detect the array update. If I create a static array like: [1,2,3,4]
the *ngFor statement correctly works and displays it like it should in the DOM.
推荐答案
我觉得有点怪,你使用的承诺的方式。它应该是你的问题的原因。作为事实上,你返回与空数组解决的承诺。该数组直接在另一边则
方法中使用。当接收到值
事件,返回这是从来没有使用过的回调中另一个承诺。
I find a bit strange the way you use promises. It should be the reason of your problem. As a matter of fact, you return a promise resolved with an empty array. This array is directly used within the then
method on the other side. When the value
event is received, you return another promise within the callback which is never used.
我觉得你应该返回一个承诺,解决它回调时为值之内收到的值
事件。
I think you should return a promise and resolve it when the values are received within the callback for the value
event.
下面是重构我会在 getTeachers
方法内提出解决您的问题:
Here is the refactoring I would propose within the getTeachers
method to fix your problem:
getTeachers() {
return new Promise((resolve, reject) => {
this.teachersRef.on("value", function(snapshot) {
var tempArr = new Array(snapshot.numChildren());
snapshot.forEach(function(data) {
var teacher = {
name: data.key(),
position: data.val().stilling
}
tempArr.push(teacher);
});
resolve(tempArr);
});
});
}
修改
有与火力地堡的code一些测试后,发现了问题的所在。事实上,使用许诺是不可能在这里,因为它们只调用一次。我的意思是中指定的回调然后
方法只适用于第一个值
事件中调用。这是承诺的缺点。
After having some tests with your code on Firebase, it found out where the problem is. In fact, using promises isn't possible here since they are only called once. I mean the callback specified within the then
method will be called only for the first value
event. This is a drawback of promises.
要超出此限制,则需要使用观测。这里是 getTeachers
法的重构版本:
To go over this restriction, you need to use observables. Here is the refactored version of the getTeachers
method:
import {Injectable} from 'angular2/core';
(...)
import {Observable} from 'rxjs/Rx';
@Injectable()
export class TeachersService {
(...)
getTeachers() {
return new Observable(observer => {
this.teachersRef.on("value", snapshot => {
var tempArr = [];
snapshot.forEach(function(data) {
var teacher = {
name: data.key(),
position: data.val().stilling
}
tempArr.push(teacher);
});
observer.next(tempArr);
}
});
}
在组件,您可以这样调用的 getTeachers
方法:
Within the component you can call the getTeachers
method like this:
@Component({
(...)
template: `
(...)
<ul>
<li *ngFor="#teacher of teachers">
<strong>{{teacher.name}}</strong>
</li>
</ul>
`,
providers: [ TeachersService ]
})
export class AppComponent {
(...)
ngOnInit() {
this.populateTeachersArr();
}
populateTeachersArr() {
this._teachersService.getTeachers().subscribe(teachers =>
this.teachers = teachers;
);
}
}
或通过利用异步
管道(这将直接管理的可观察对象)走得更远:
or go further by leveraging the async
pipe (which will directly manages the observable object):
@Component({
(...)
template: `
(...)
<ul>
<li *ngFor="#teacher of (teachers | async)">
<strong>{{teacher.name}}</strong>
</li>
</ul>
`,
providers: [ TeachersService ]
})
export class AppComponent {
(...)
ngOnInit() {
this.populateTeachersArr();
}
populateTeachersArr() {
this.teachers = this._teachersService.getTeachers();
}
}
希望它可以帮助你,
蒂埃里
Hope it helps you, Thierry
这篇关于当角阵更新2不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!