2016-12-20 43 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