2016-09-16 205 views
7

我很難理解如何將組件內的屬性更改傳播到實際視圖,而無需從UI觸發事件。如果我來回更新UI。Ionic 2 - 對模型的更改未在視圖/ UI中更新

這是我的組件,它每秒鐘檢索一次BLE通知。通知的結果值需要在每個通知後的視圖中更新。我可以看到在開發者控制檯中顯示的通知。

import { Component, ChangeDetectionStrategy, ChangeDetectorRef, Input, Output} from '@angular/core'; 
import { NavController, NavParams } from 'ionic-angular'; 
import { BLE } from 'ionic-native'; 
import {Observable} from 'rxjs/Observable'; 


@Component({ 
templateUrl: 'build/pages/devices/devices.html', 
//changeDetection: ChangeDetectionStrategy.OnPush 
}) 

export class DevicePage { 

private nav:NavController = null; 
private navParams:NavParams = null; 
private device:any; 
private connecting:any; 
private characteristics:any; 
private data:any; 
private temp:any; 


static get parameters() { 
    return [[NavParams],[NavController]]; 
} 
// 
constructor(navParams, nav, private cd:ChangeDetectorRef) { 
    this.nav = nav; 
    this.navParams = navParams; 
    this.device = this.navParams.get('device'); 
    this.connect(this.device.id); 
} 

connect(device) { 
/* 
    var service = "6e524635-312d-444b-2020-202020202020"; 
    var characteristic_read = "6e524635-312d-444b-2062-7574746f6e20"; 
    var characteristic_write = "6e400002-b5a3-f393-e0a9-e50e24dcca9e" 
*/ 
    var bleUART = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; 
    var RXD = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"; 
    var TXD = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"; 
    //this.hello = "Hello"; 
    BLE.connect(device).subscribe(
    peripheralData => { 
     console.log("Connect:" + JSON.stringify(peripheralData)); 
     BLE.startNotification(device, bleUART, RXD).subscribe(
      buffer => {this.temp = String.fromCharCode.apply(null, new Uint8Array(buffer)); 
      // this.cd.markForCheck(); 
       this.cd.detectChanges(); 
      console.log("Data: " + this.temp); 
      }, 
      error => {console.log("Error Notification" + JSON.stringify(error)); 
     })}, 
     error => {console.log("Error Connecting" + JSON.stringify(error));}) 
    } 
} 

相應的HTML:

<ion-navbar *navbar> 
    <ion-title> 
    Devices 
    </ion-title> 
    <ion-buttons end> 
    <button (click) = "startScanning()">Scan</button> 
    </ion-buttons> 
</ion-navbar> 

<ion-content> 
    <ion-list insert> 
    <ion-item-sliding *ngFor="#device of devices" #slidingItem> 
     <button ion-item (click)="connectToDevice(device)"> 
     <h2>{{device.name}}</h2> 
     <p>{{device.id}}</p> 
     <p>{{device.rssi}}</p> 
     </button> 
    </ion-item-sliding> 
    </ion-list> 
    <ion-spinner *ngIf="isScanning==true" name="circles"></ion-spinner> 
</ion-content> 

<ion-header> 
<ion-navbar> 
    <ion-title> 
    Hotplate Status 
    </ion-title> 
</ion-navbar> 
</ion-header> 

<ion-content> 
    <h2>Connected Device:</h2> 
    <p>{{device.name}}</p> 
    <h1>Temperature:</h1> 
    <p>{{temp}}</p> 

</ion-content> 

添加根頁,以從那裏connect()被稱爲

import { Component } from '@angular/core'; 
import { NavController } from 'ionic-angular'; 
import { DevicePage } from '../devices/devices'; 
import { BLE } from 'ionic-native'; 

@Component({templateUrl: 'build/pages/home/home.html'}) 

export class HomePage { 
    private nav:NavController = null; // please add this line as default generated page plus the --ts option on command line. 
    private devices:any; 
    private isScanning:any; 

    static get parameters() { 
    return [[NavController]]; 
    } 

    constructor(nav:NavController) { 
    this.nav = nav; 
    this.devices = []; 
    this.isScanning = false; 
    } 

    startScanning() { 
    console.log('Scanning Started'); 
    this.devices = []; 
    this.isScanning = true; 
    BLE.startScan([]).subscribe(device => { 
    this.devices.push(device); 
    }); 

    setTimeout(() => { 
    BLE.stopScan().then(() => { 
     console.log('Scanning has stopped'); 
     console.log(JSON.stringify(this.devices)) 
     this.isScanning = false; 
    }); 
    }, 5000); 
    } 

    connectToDevice(device) { 
    console.log('Connect To Device'); 
    console.log(JSON.stringify(device)) 
    this.nav.push(DevicePage, { 
    device: device 
    }); 
} 
} 

和相應的HTML顯示

我試着嘗試更改檢測,但markForCheck()導致異常。當我直接使用NgZone時會顯示類似的TypeError。

Uncaught TypeError: Cannot read property 'markForCheck' of undefined(anonymous function) @ app.bundle.js:84SafeSubscriber.__tryOrUnsub @ app.bundle.js:94435SafeSubscriber.next @ app.bundle.js:94384Subscriber._next @ app.bundle.js:94334Subscriber.next @ app.bundle.js:94298cordova.callbackFromNative @ cordova.js:293processMessage @ cordova.js:1081processMessages @ cordova.js:1104pollOnce @ cordova.js:973pollOnceFromOnlineEvent @ cordova.js:960

我使用的是最新的Ionic2 Beta版。 任何想法我在這裏做錯了嗎?

感謝, 延

+0

你叫'連接()'只從構造函數(在你的代碼所示),或者也可在別的地方? –

+0

不,只有從構造函數調用'connect()'。我編輯了最初的帖子並添加了javascript和html。 –

回答

3

您需要添加ChangeDetectorRef到PARAMS

return [[NavParams],[NavController],[ChangeDetectorRef]]; 
+1

好的,太棒了!此外,我不得不將'this.cd.markForCheck()'更改爲'this.cd.detectChanges()'但現在UI在每次通知後都會更新。非常感謝! –

+1

是的!這篇文章是一個4小時彩虹結束時的金罐。首先,它引導我進入「ChangeDetector」,我不知道它存在,它似乎是Angular 2的「$ scope。$ apply()」版本 - 第二個例子給了我一個如何實現的好例子。謝謝你們!最後,像魅力一樣工作。 – mpsyp