Thameur Daly
Thameur Daly

Reputation: 319

How to search array items in Ionic 3?

Please I'm using a model name ResProject and variable resProject : Observable ;

this is my code :

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Observable } from "rxjs";    

@IonicPage()
@Component({
  selector: 'page-project',
  templateUrl: 'project.html',
})
export class ProjectPage {
  resProject : Observable <ResProject[]> ;
  constructor(public navCtrl: NavController, 
              public navParams: NavParams)

and for the models of ResProject its like that :

export interface ResProject {
    key?: string;
    type : string ;
    name : string; 
    nbrUnit : number ; 
    nbrFloor : number ;
}

and for the HTML this is my code :

   <ion-item *ngFor="let rp of resProject  | async" detail-push navPush="ViewProjectPage" [navParams]="{resProject:rp} "  >
    {{rp.name}}
  </ion-item>

Please note that i get the data of Resproject from firebase.

How can i filter this list of ResProject in my ion-serchbar or any other solutions?

Upvotes: 1

Views: 4183

Answers (2)

Sergey Rudenko
Sergey Rudenko

Reputation: 9235

In your case you seem to be using Observables (Rxjs), and these are not Arrays hence you can not use .filter etc array methods directly with Observables. You can either implement filter using Observable's operator "filter": https://www.learnrxjs.io/operators/filtering/filter.html

Or you can just subscribe to your service (that returns Observable) in the constructor and then make your template work using arrays (and hence yo won't need async pipe in the template).

Try to do the following in your TS:

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Observable } from "rxjs";
import { ResProject,ComProject,OffiProject } from "../../models/project.model";
import { AddProjectService } from "../../services/addproject.service";

@IonicPage()
@Component({
  selector: 'page-project',
  templateUrl: 'project.html',
})
export class ProjectPage {

  // holders of original unfiltered data:
  resProject : Observable <ResProject[]> ;
  comProject : Observable <ComProject[]>;

  // holders of data for filtered lists, initially set to empty array:
  filteredResProject: any[] = [];
  filteredComProject: any[] = [];

  constructor(public navCtrl: NavController, 
              public navParams: NavParams,
              public projectService : AddProjectService,
              ) 
    { 
      this.initializeItems();
    }

  filterItems(event) {
    this.initializeItems();
    const val = event.target.value;
    if (val && val.trim() != '') {
      this.filteredResProject = this.filteredResProject.filter((item) => {
        return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
      })
    }
  }

  initializeItems() {
    this.resProject = this.projectService.getResProjectList()
    .snapshotChanges()
    .map(
      changes => {
        return changes.map(c => ({
          key : c.payload.key, ...c.payload.val()
        }))
      }

    )
  this.resProject.subscribe( res => {
    this.filteredResProject = res;
  })

  this.comProject = this.projectService.getComProjectList()
  .snapshotChanges()
  .map(
    changes => {
      return changes.map(c => ({
        key : c.payload.key, ...c.payload.val()
      }))
    }

  )
this.comProject.subscribe( res => {
  this.filteredComProject = res;
});
  }

}

And in your template yoo should not be using async pipe anymore as you only render arrays based data:

<ion-header>
    <ion-navbar>
      <button ion-button menuToggle>
        <ion-icon name="menu"></ion-icon>
      </button>
    <ion-title>Project List</ion-title>
  </ion-navbar>
  <ion-toolbar>
    <ion-searchbar (ionInput)="filterItems($event)"></ion-searchbar>
  </ion-toolbar>
</ion-header>

<ion-content >
    <ion-list>
        <ion-list-header>
        Project List
        </ion-list-header>
        <ion-badge>Number Of Residential Project :{{ resProject.length }}</ion-badge>
        <ion-item *ngFor="let rp of filteredResProject" detail-push navPush="ViewProjectPage" [navParams]="{resProject:rp} ">
        {{rp.name}}
      </ion-item>
    </ion-list>
    <ion-list>
        <ion-badge color="danger">Number Of Commercial Project :{{ comProject.length }}</ion-badge>
        <ion-item *ngFor="let cp of filteredComProject" detail-push navPush="ViewComProPage" [navParams]="{comProject:cp}">
        {{cp.name}}
      </ion-item>
    </ion-list>
</ion-content>

This is not the best code design tbh but based on your current code this should work. Basic idea - you want to obtain full truth data from your service and on each "initialize" you only modify filtered lists.

Upvotes: 0

Sudarshana Dayananda
Sudarshana Dayananda

Reputation: 5265

You can use filter method to filter array items as below.

home.html

<ion-content padding>
<ion-searchbar (ionInput)="filterItems($event)"></ion-searchbar>
<ion-list>
  <ion-item *ngFor="let item of resProject">
    {{ item.name }}
  </ion-item>
</ion-list>
</ion-content>

HomePage.ts

export class HomePage {

  resProject: any[];

  constructor() {

   this.initializeItems();
  }

  filterItems(event) {

    this.initializeItems();
    const val = event.target.value;
    if (val && val.trim() != '') {
      this.resProject = this.resProject.filter((item: ResProject) => {
        return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
      })
    }
  }

  initializeItems() {
    this.resProject = [
      { name: "Andrew" },
      { name: "Micheal" }, 
      { name: "Bernad" },
      { name: "Charles" }, 
      { name: "David" }];
  }
}

export interface ResProject {
    name : string; 
}

Hope this will help you. find working demo here

Upvotes: 1

Related Questions