Searchbar on firebase dataset

#1

Hi everyone,

I need help for filtering a dataset provided by my firebase database. I use AngularFire2 to get my data (see my provider at the end of this post) in a Observable<any[]>;

Next, i added a searchbar to filtering my dataset but the code below doesn’t work. I can retrieve the good filtered data but my Observable<any[]> doesn’t refresh…It works well on type any[] but in my case my dataset must be a Observable<any[]>

Home.html

<ion-header>
  <ion-navbar color="maintheme">
   </ion-navbar>
  <ion-searchbar class="searchbar" (ionInput)="onSearch($event)"></ion-searchbar>
</ion-header>

<ion-content class="window">
    <ion-card *ngFor="let item of items | async ; let idx=index">
      <ion-card-header class="cardHeader" no-padding>
        <ion-item class="leftPadding" no-lines no-padding>
              {{item.title}}
        </ion-item>
     </ion-card-header>
   </ion-card>
</ion-content>

Home.ts

export class HomePage implements OnInit{

   items: Observable<any[]>;

 constructor(public navCtrl: NavController,
    public dataService: DataProvider, 
    public loadingCtrl: LoadingController,
    public alertCtrl: AlertController,
    private authService: AuthProvider) {
  }

ngOnInit(){ ... }

/**
   * Refresh dataset
   */
  onRefresh(){
    const loading = this.loadingCtrl.create({content: 'Loading please wait...'});
    try{
      this.items= this.dataService.fetchData();
      this.items.subscribe(res => {
        loading.dismiss();
      },
      error => {
        loading.dismiss();
      });
    } catch(err){
      loading.dismiss();
    }
  }


onSearch(ev: any){
    this.onRefresh();
    
    // set searchText to the value of the searchbar
    var searchText = ev.target.value;
    
    // Avoid research if searchtext is empty
    if (!searchText || searchText.trim() === '') {
      return;
    }

    // Filtering on the attribute 'title'
    this.items= this.items.filter((v) => {
      v.forEach(element => {
        if (element.title.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1) {
          console.log('add ' + element.title);   // Here, the filtered item is good
          return true;
        }
      });
      return false;
    })
  }

My data provider

import { AngularFireAuth } from 'angularfire2/auth';
import { Injectable } from '@angular/core';
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { ToolProvider } from '../tool/tool';

@Injectable()
export class DataProvider {

  itemList: AngularFireList<any>;
  items: Observable<any[]>;


  constructor(public afDB: AngularFireDatabase, private tool: ToolProvider, private afAuth: AngularFireAuth) {
      // some stuff here
  }

  fetchData(){
     try{
      this.itemList = this.afDB.list('/items/'+this.user, ref => ref.orderByChild('type'));
      this.items= this.itemList.valueChanges().map(items => items.sort(this.tool.predicateBy("title")));
      return this.items;  
    } catch(err){
      this.items= null;
    }
  }

Thank you all

Guillaume

#2

Have you solved this issue?

#3

Struggling with the same thing. About to conclude it is impossible to filter Observables. I tried to put the retrieved data into an array and filter that but that was also unsuccessful. A lot of issues… if anybody has any solution, please share