当角阵更新2不更新 [英] Angular 2 not updating when array is updated

查看:121
本文介绍了当角阵更新2不更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有通过火力获取某些对象的服务。然后它填充的阵列应该然后提示角度来更新与一个* 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆