2016-12-20 83 views
1

我試圖在ListView中異步顯示簡單的消息。這些消息是通過the de-facto standard NativeScript Plugin從Firebase獲取的。我認爲我的插件交互沒有任何問題,因爲我可以初始化,登錄甚至收到消息。我只是無法讓他們在ListView中顯示。在NativeScript中異步顯示來自Firebase的消息ListView

我設法通過創建EventEmitter將Firebase消息中的事件回調映射到observable。我不知道這是否是正確的路要走,但它已經顯示出最好的結果,因爲我可以看到通過我的可觀察到的消息。

下面是我在做什麼:

import { Component, OnInit, EventEmitter } from "@angular/core"; 
import { Observable } from "rxjs/Observable"; 
import * as firebase from "nativescript-plugin-firebase"; 
import { Message } from "./shared/message.model"; 
@Component({ 
    selector: "my-app", 
    templateUrl: "app.component.html" 
}) 
export class AppComponent implements OnInit { 
    public messages: Observable<Array<Message>>; 

    ngOnInit() { 
     this.init() 
      .then(() => this.login()) 
      .then(() => this.getMessages()); 
    } 

    // ... implementations for init() and login(), also post()-method 

    getMessages =() => { 
     let msgs = []; 
     // initialize with asynchronous behaviour 
     let emitter = new EventEmitter(true); 
     this.messages = emitter; 
     // shows messages getting added to array 
     this.messages.subscribe((a) => console.log(JSON.stringify(a))); 

     firebase.addChildEventListener((result) => { 
      msgs.push(new Message(result.value.text, result.value.timestamp)); 
      emitter.next(msgs); 
     }, "/messages"); 
    } 
} 

這是視圖:

<GridLayout rows="auto, *"> 
    <GridLayout row="0" columns="*, auto"> 
     <TextField #textInput hint="Type message..." col="0"></TextField> 
     <Button text="Post" (tap)="post(textInput)" col="1"></Button> 
    </GridLayout> 

    <ListView row="1" [items]="messages | async"> 
     <template let-item="msg"> 
      <StackLayout> 
       <Label text="a message"></Label> <!-- displays after button click --> 
       <Label [text]="msg.text"></Label> <!-- results in exception when there even are items --> 
      </StackLayout> 
     </template> 
    </ListView> 
</GridLayout> 

我可以看到訂閱工作,只要每個數組變種會記錄增量,但我的觀點並沒有顯示它們。我嘗試了ChangeDetectionStragety的不同模式,這似乎沒有什麼區別。

我發現,當我在視圖中有一個按鈕調用組件函數時,我可以在單擊它後看到這些元素。然而,如果有綁定到鬆懈的變量在我看來像[text]="msg.text"應用程序崩潰,出現以下錯誤:

An uncaught Exception occurred on "main" thread. 
com.tns.NativeScriptException: 
Calling js method getView failed 
[object Object] 
File: "/data/data/org.nativescript.firebasetest/files/app/tns_modules/@angular/core/bundles/core.umd.js, line: 9464, column: 20 
StackTrace: 
Frame: function:'ListViewComponent.detectChangesOnChild', file:'/data/data/org.nativescript.firebasetest/files/app/tns_modules/nativescript-angular/directives/list-view-comp.js', line: 134, column: 29 
Frame: function:'ListViewComponent.onItemLoading', file:'/data/data/org.nativescript.firebasetest/files/app/tns_modules/nativescript-angular/directives/list-view-comp.js', line: 114, column: 14 
Frame: function:'Observable.notify', file:'/data/data/org.nativescript.firebasetest/files/app/tns_modules/data/observable/observable.js', line: 146, column: 32 
Frame: function:'ListViewAdapter.getView', file:'/data/data/org.nativescript.firebasetest/files/app/tns_modules/ui/list-view/list-view.js', line: 199, column: 28 
// ... native stacktrace 

我在做什麼錯?爲什麼要在NativeScript中實現一個異步列表非常困難,因爲它在Angular中很容易實現?該文件是在這裏有點弱..

回答

2

你的火力點連接器正在運行的角區之外,也許您的包裹下的呼叫在ngZone.run幫助:

import { Component, OnInit, EventEmitter, NgZone } from "@angular/core"; 
import { Observable } from "rxjs/Observable"; 
import * as firebase from "nativescript-plugin-firebase"; 
import { Message } from "./shared/message.model"; 
@Component({ 
    selector: "my-app", 
    templateUrl: "app.component.html" 
}) 
export class AppComponent implements OnInit { 
    public messages: Observable<Array<Message>>; 

    constructor(private ngZone: NgZone) {} 

    ngOnInit() { 
     this.init() 
      .then(() => this.login()) 
      .then(() => this.getMessages()); 
    } 

    // ... implementations for init() and login(), also post()-method 

    getMessages =() => { 
     let msgs = []; 
     // initialize with asynchronous behaviour 
     let emitter = new EventEmitter(true); 
     this.messages = emitter; 
     // shows messages getting added to array 
     this.messages.subscribe((a) => console.log(JSON.stringify(a))); 

     firebase.addChildEventListener((result) => { 
      this.ngZone.run(() => { 
       msgs.push(new Message(result.value.text, result.value.timestamp)); 
       emitter.next(msgs); 
      }); 
     }, "/messages"); 
    } 
} 

而且這可能幫助:https://github.com/NathanWalker/angular-seed-advanced/wiki/How-to-integrate-Firebase-across-all-platforms-(web-nativescript-desktop)

+0

謝謝,這對我非常有幫助。我的觀點現在枚舉消息,但是我仍然無法綁定到我的模板中的消息屬性,而沒有得到前面的「getView失敗」 - 異常。有關於此的任何想法? – nilo

+0

修復它像尼克Iliev建議 – nilo

3

除了ngZone相關的問題之外,項目模板中還有一個語法錯誤。更改此<template let-item="msg">

<template let-msg="item"> 

詳見this thread

+1

你是對的,我通過在某個步驟中命名它「項目」使它工作,但我沒有完全掌握我所做的修復它。非常感謝你的幫助,可惜我只能接受一個正確答案。 – nilo