ionic:ng在数组

时间:2018-03-01 15:00:34

标签: angular ionic-framework ionic3 ngfor

离子新手在这里。我使用的是Ionic 3和BLE插件。此插件的工作方式是您开始扫描蓝牙设备,每次新的扫描结果都会通知您,然后在您完成后取消扫描。我每次收到新的扫描结果时都会尝试将元素附加到ion-list

这个Cordova插件使用回调,其中离子包含在Observables和Promises中。方法startScan会返回Observable<any>,并且&#34;任何&#34;}是一个对象,包含有关检测到的BLE设备的信息。

我首先尝试将此observable直接插入ngFor:

<ion-list>
    <button ion-item *ngFor="let result of results | async">
        {{ result | json}}
    </button>  
</ion-list>

开始扫描的调用返回了observable:

this.results = this.ble.startScan([]);
this.results.subscribe(...);

但是我听说ngFor仅适用于数组,因此需要Observable<Array>而不是单个对象的可观察对象。所以我放弃了Observable并使用了一个数组。异步管道不再工作,所以我不得不修改列表:

<ion-list>
    <button ion-item *ngFor="let result of results">
        {{ result | json}}
    </button>  
</ion-list>

然后将results的类型更改为Array<any>。扫描代码现在看起来像这样:

this.ble.startScan([])
.subscribe(device => {
    this.results.push(device); //Does not work    
});

但是直到屏幕中的某些其他组件发生变化才会显示该列表。显然,Angular不会检测Array元素内部的更改,它只检测对象内部引用和属性的更改。所以我已经尝试过这个不合理的黑客攻击了:

this.ble.startScan([])
.subscribe(device => {
    this.results = this.results.concat([device]); //Does not work    
});

但即使这样也行不通。然后经过几个小时的阅读后,我知道这个名为ChangeDetector的东西,据称应该这样做。我尝试了OnPush检测策略,默认情况下无效:

this.ble.startScan([])
.subscribe(device => {
    this.results = this.results.concat([device]);
    this.changeDetector.markForCheck() //Does not work    
});

当然它不起作用,因为它只标记检查,但不会在那一刻执行检查。

TL; DR ELI5你需要在Ionic(或Angular)中将一个元素添加到列表中吗?

4 个答案:

答案 0 :(得分:5)

尝试使用detectChanges()代替markForCheck()

也许你想看看this aproach

作者使用ngZones run()将找到的设备添加到列表中,其中包括changeDetection。非常有趣的imho。这是nice article about ngZone

答案 1 :(得分:2)

这是最终奏效的:

this.ble.startScan([])
.subscribe(device => {
    this.results.push(device);
    this.changeDetector.detectChanges();
});

答案 2 :(得分:1)

我发现的另一个解决方案是使用对页面上运行的Angular应用程序的引用,请参见以下link,并将其称为tick()方法以显式处理更改检测及其副作用。我在Ionic中所做的事情如下:

import { ApplicationRef } from '@angular/core';
export class HomePage {
  constructor ( private app: ApplicationRef ) {}

  .. my code ...

  this.app.tick();  //start change detection to cause a screen update
}

答案 3 :(得分:-2)

您根本不必将数据推送到列表中。

   Consider you are returning data

    shoppingItems: FirebaseListObservable<any[]>;

    this.shoppingItems = af.list('/Items', {
        query: {
            limitToLast: 1000

        }
    });


   If you are not using firebase then just return the data from service directly as below.

 this.shoppingItems = http('your service url'); 

HTML

<ul *ngFor="let item of shoppingItems | async" >

<li>{{item.name}} </li>

</ul>