视图使用基于Observable:
的* ngFor列出条目view.html
<ion-searchbar [(ngModel)]="filter" (ionInput)="filterMeds()"></ion-searchbar>
<ion-list>
<ion-item *ngFor="let medicine of getMeds$() | async">
{{medicine.name}}
</ion-item>
</ion-list>
组件只通过getMeds $()函数中继一个observable:
component.ts
private _refreshOnInput$: Subject<any> = new Subject();
getMeds$(){
return this.medsService.medsArray$;
}
服务本身只是将数组作为可观察对象返回:Observable<Medicine[]>
医学是由一些数字组成的普通物体。
现在,我的问题是:view.html添加了一个搜索栏。每当用户修改搜索条件时,都会调用filterMeds()
函数:
filterMeds(){
this._refreshOnInput$.next(true);
}
这是在blog post之后(cmd -f文本&#34;刷新按钮&#34;看看我尝试实施的内容)。
我理解我的* ngFor必须迭代一个observable,它会在应用一些过滤后合并原始this.medsService.medsArray$
和_refreshOnInput()
。
** component.ts尝试**
filteredMeds$: Observable<Medicine[]>
// Constructor
// An event is fired whenever the search input's updated
filteredMeds$ = this._refreshOnInput$.map( () =>
this.medsService.medsArray$
.map(meds =>
meds.filter(med =>
med.name.toLowerCase().indexOf(this.filter.toLowerCase()) > -1
)
)
);
this.meds$ = Observable.merge(this.medsService.medsArray$, filteredMeds$);
// Updating the getMeds$() method:
getMeds$(){
return this.medsService.medsArray$;
}
我无法弄清楚如何创建有效的过滤流。当我直接将filteredMeds $ observable提供给* ngFor:
时,会发生同样的错误ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed
答案 0 :(得分:1)
我猜你应该以这种方式迭代(getMeds$() | async)
:
<ion-item *ngFor="let medicine of (getMeds$() | async)">
因为在您的示例中,您在 medicine 对象上使用异步管道,没有 getMeds $ 方法的结果。
但更好的方法是使用公共引用medsService(在组件中),你的ngFor循环应该是这样的:
<ion-item *ngFor="let medicine of (medsService.medsArray$ | async)">
因为你不应该在html中使用方法(作为ngFor循环或ngIf条件的参数)。在您的情况下,视图中的每个更改都将被称为getMeds $()方法,这对Observables来说完全没有必要。
答案 1 :(得分:0)
也许这不是最好的解决方案,但它有效。所以,请评论这种方法:
private _refreshMeds: Subject<any> = new Subject();
meds$: Observable<any>;
filter: string = '';
constructor(@Inject(MedsService) private medsService: MedsService) {
let filtered$ = new Observable( obs => {
this._refreshMeds.subscribe( () =>
this.medsService.medsArray$.first().subscribe( medsArray => {
const filteredMeds = medsArray.filter(med =>
(this.filter.length === 0 ) ||
(med.name.toLowerCase().indexOf(this.filter.toLowerCase()) > -1));
obs.next(filteredMeds);
})
)
});
// Merging both the unfiltered (ie. at page load) or the filtered version
this.meds$ = Observable.merge(this.medsService.medsArray$, filtered$);
}
// Called by the input's changed listener (ionic: ionInput)
filterMeds(){
this._refreshMeds.next(true);
}