Angular 2 - 模型更改后视图不更新 [英] Angular 2 - View not updating after model changes

查看:22
本文介绍了Angular 2 - 模型更改后视图不更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的组件,它每隔几秒调用一个 REST api 并接收回一些 JSON 数据.我可以从我的日志语句和网络流量中看到,返回的 JSON 数据正在改变,我的模型正在更新,但是,视图没有改变.

我的组件看起来像:

import {Component, OnInit} from 'angular2/core';从'../services/recentdetection.service'导入{RecentDetectionService};从'../model/recentdetection'导入{RecentDetection};从 'rxjs/Rx' 导入 {Observable};@成分({选择器:'最近检测',templateUrl: '/app/components/recentdetection.template.html',提供者:[RecentDetectionService]})导出类RecentDetectionComponent 实现OnInit {最近检测:阵列;构造函数(私有最近检测服务:RecentDetectionService){this.recentDetections = new Array();}getRecentDetections():无效{this.recentDetectionService.getJsonFromApi().subscribe(recent => { this.recentDetections = 最近;console.log(this.recentDetections[0].macAddress) });}ngOnInit() {this.getRecentDetections();让计时器 = Observable.timer(2000, 5000);timer.subscribe(() => this.getRecentDetections());}}

我的观点如下:

<!-- 默认面板内容--><div class="panel-heading"><h3>最近检测到</h3></div><div class="panel-body"><p>最近检测到的设备</p>

<!-- 表--><table class="table" style="table-layout: fixed; word-wrap: break-word;"><头><tr><th>Id</th><th>供应商</th><th>时间</th><th>Mac</th></tr></thead><身体><tr *ngFor="#detected of recentDetections"><td>{{detected.broadcastId}}</td><td>{{detected.vendor}}</td><td>{{detected.timeStamp |日期:'yyyy-MM-dd HH:mm:ss'}}</td><td>{{detected.macAddress}}</td></tr></tbody>

我可以从 console.log(this.recentDetections[0].macAddress) 的结果中看到,recentDetections 对象正在更新,但视图中的表永远不会改变,除非我重新加载页面.

我正在努力寻找我在这里做错了什么.有人可以帮忙吗?

解决方案

可能是您服务中的代码以某种方式超出了 Angular 的区域.这会破坏更改检测.这应该有效:

import {Component, OnInit, NgZone} from 'angular2/core';导出类RecentDetectionComponent 实现OnInit {最近检测:阵列;构造函数(私有区域:NgZone,//<== 添加私人最近检测服务:最近检测服务){this.recentDetections = new Array();}getRecentDetections():无效{this.recentDetectionService.getJsonFromApi().订阅(最近 => {this.zone.run(() => {//<== 添加this.recentDetections = 最近;console.log(this.recentDetections[0].macAddress)});});}ngOnInit() {this.getRecentDetections();让计时器 = Observable.timer(2000, 5000);timer.subscribe(() => this.getRecentDetections());}}

有关调用变更检测的其他方法,请参阅在 Angular 中手动触发变更检测

调用变更检测的替代方法是

ChangeDetectorRef.detectChanges()

立即对当前组件及其子组件运行更改检测

ChangeDetectorRef.markForCheck()

在 Angular 下次运行更改检测时包含当前组件

ApplicationRef.tick()

为整个应用程序运行变更检测

I have a simple component which calls a REST api every few seconds and receives back some JSON data. I can see from my log statements and the network traffic that the JSON data being returned is changing, and my model is being updated, however, the view isn't changing.

My component looks like:

import {Component, OnInit} from 'angular2/core';
import {RecentDetectionService} from '../services/recentdetection.service';
import {RecentDetection} from '../model/recentdetection';
import {Observable} from 'rxjs/Rx';

@Component({
    selector: 'recent-detections',
    templateUrl: '/app/components/recentdetection.template.html',
    providers: [RecentDetectionService]
})



export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => { this.recentDetections = recent;
             console.log(this.recentDetections[0].macAddress) });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
}

And my view looks like:

<div class="panel panel-default">
    <!-- Default panel contents -->
    <div class="panel-heading"><h3>Recently detected</h3></div>
    <div class="panel-body">
        <p>Recently detected devices</p>
    </div>

    <!-- Table -->
    <table class="table" style="table-layout: fixed;  word-wrap: break-word;">
        <thead>
            <tr>
                <th>Id</th>
                <th>Vendor</th>
                <th>Time</th>
                <th>Mac</th>
            </tr>
        </thead>
        <tbody  >
            <tr *ngFor="#detected of recentDetections">
                <td>{{detected.broadcastId}}</td>
                <td>{{detected.vendor}}</td>
                <td>{{detected.timeStamp | date:'yyyy-MM-dd HH:mm:ss'}}</td>
                <td>{{detected.macAddress}}</td>
            </tr>
        </tbody>
    </table>
</div>

I can see from the results of console.log(this.recentDetections[0].macAddress) that the recentDetections object is being updated, but the table in the view never changes unless I reload the page.

I'm struggling to see what I'm doing wrong here. Can anyone help?

解决方案

It might be that the code in your service somehow breaks out of Angular's zone. This breaks change detection. This should work:

import {Component, OnInit, NgZone} from 'angular2/core';

export class RecentDetectionComponent implements OnInit {

    recentDetections: Array<RecentDetection>;

    constructor(private zone:NgZone, // <== added
        private recentDetectionService: RecentDetectionService) {
        this.recentDetections = new Array<RecentDetection>();
    }

    getRecentDetections(): void {
        this.recentDetectionService.getJsonFromApi()
            .subscribe(recent => { 
                 this.zone.run(() => { // <== added
                     this.recentDetections = recent;
                     console.log(this.recentDetections[0].macAddress) 
                 });
        });
    }

    ngOnInit() {
        this.getRecentDetections();
        let timer = Observable.timer(2000, 5000);
        timer.subscribe(() => this.getRecentDetections());
    }
}

For other ways to invoke change detection see Triggering change detection manually in Angular

Alternative ways to invoke change detection are

ChangeDetectorRef.detectChanges()

to immediately run change detection for the current component and its children

ChangeDetectorRef.markForCheck()

to include the current component the next time Angular runs change detection

ApplicationRef.tick()

to run change detection for the whole application

这篇关于Angular 2 - 模型更改后视图不更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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