# Having a hard time showing filtered observable

**URL:** <https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690>\
**Category:** ionic-v3\
**Created:** [May 24, 2019, 3:37pm UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690 "2019-05-24T15:37:04Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![JohnCressman](https://avatars.discourse-cdn.com/v4/letter/j/c68b51/32.png) [@JohnCressman](https://forum.ionicframework.com/u/JohnCressman)\
**Post date:** [May 24, 2019, 3:37pm UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690/1 "2019-05-24T15:37:04Z")

</div>

I’m trying to build something fairly straightforward. I am reading in a json file using an observable. This works. No problem.

I am then trying to allow a search for the content in the list. When I altered the code to make it searchable, nothing works.

If I change the ion-list to look at results, it works and displays the list. If I change it to look at information, it doesn’t work.

```auto
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>
    <ion-title>Hospitals</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-searchbar [(ngModel)]="searchTerm" (ionChange)="searchChanged()"></ion-searchbar>
  <ion-list *ngIf="information">
    <ion-item button *ngFor="let item of (information | async)" routerDirection="forward" [routerLink]="['/hospital-details/'+ item.id]">
      <ion-label text-wrap>
        <h3>{{ item.name }}</h3>
      </ion-label>
    </ion-item>
  </ion-list>

</ion-content>

```

ts file

```auto
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Routes, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { GetHospitalsService } from '../../services/get-hospitals.service';
import { SearchPipe } from './../../search.pipe';
import {filter, map} from 'rxjs/operators';

@Component({
  selector: 'app-hospitals',
  templateUrl: './hospitals.page.html',
  styleUrls: ['./hospitals.page.scss'],
})
export class HospitalsPage implements OnInit {

  // information = null;
  hospitals = null;
  searchTerm = '';

  results: Observable<any>;
  information: Observable<any>;

  constructor(private activatedRoute: ActivatedRoute, private hospitalService: GetHospitalsService, private router: Router) { }
  ngOnInit() {
    console.log('Hospitals enter');

    this.results = this.hospitalService.getHospitals1();
    this.information = this.filterArr2(this.searchTerm);

  }
  filterArr2(search): Observable<any> {
    return this.results.pipe(
          map(oneObj => oneObj.name.toLowerCase().indexOf(search) > -1)
      );
  }

  searchChanged() {
    const mySearch = this.searchTerm.toLowerCase();
    this.information = this.filterArr2(mySearch);
  }

}

```

Error message

```auto
ERROR TypeError: Cannot read property 'toLowerCase' of undefined
    at MapSubscriber.project (hospitals.page.ts:34)

```

Here is a pic of what I get when I switch it to results.

 ![2019-05-24_11-34-17](https://global.discourse-cdn.com/ionicframework/original/3X/c/6/c62f722421731d59f6b2c0c40c196257e938b68c.png)

If I change it to a subscribe, I get a different error, something like:

# [InvalidPipeArgument: ‘[object Object][object Object][object Object][object Object]’ for pipe ‘AsyncPipe’](https://stackoverflow.com/questions/44866124/angular-4-invalidpipeargument-object-object-for-pipe-asyncpipe)

Please, can anyone tell me the RIGHT way to do this? I’m banging my head against the desk so much I’m giving myself a concussion.

---

<div class="post-metadata">

**Author:** ![reedrichards](https://avatars.discourse-cdn.com/v4/letter/r/34f0e0/32.png) [@reedrichards](https://forum.ionicframework.com/u/reedrichards)\
**Post date:** [May 25, 2019, 5:56am UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690/2 "2019-05-25T05:56:02Z")

</div>

Try to use `(ionInput)` instead of `ngModel` to assign the inputed value to `searchTerm`.

Your first error, `Cannot read property 'toLowerCase' of undefined`, displays that `searchTerm` is null when you try to transform it in `toLowerCase`

Maybe (not sure):

```auto
(ionInput)="something($event)"

```

```auto
something($event) {
        this.searchTerm = $event.target.value;
}

```

---

<div class="post-metadata">

**Author:** ![Tommertom](https://avatars.discourse-cdn.com/v4/letter/t/ed8c4c/32.png) [@Tommertom](https://forum.ionicframework.com/u/Tommertom)\
**Post date:** [May 25, 2019, 10:32am UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690/3 "2019-05-25T10:32:55Z")

</div>

Hi

A few things I see or wonder

- You use map to filter results, but you should use the filter operator
- I wonder if the search results will get updated as the search action will not trigger the observable to emit a new list which you can filter. For each search change you would need to reget the observable from hospitalService. Try to refactor your code without using async to see if it at all works.
- I would think the undefined error pops up because an entry in the data does not have a name field. Try console.log in the filter function

Some ideas

Regards

Tom

---

<div class="post-metadata">

**Author:** ![danieldugger](https://avatars.discourse-cdn.com/v4/letter/d/ad7895/32.png) [@danieldugger](https://forum.ionicframework.com/u/danieldugger)\
**Post date:** [May 25, 2019, 9:32pm UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690/4 "2019-05-25T21:32:16Z")

</div>

You will definitely need to pass in the event to your function and can do so using the searchbar control.

You’ll also want to filter after setting information equal to the object that contains the data from your http call.

---

<div class="post-metadata">

**Author:** ![JohnCressman](https://avatars.discourse-cdn.com/v4/letter/j/c68b51/32.png) [@JohnCressman](https://forum.ionicframework.com/u/JohnCressman)\
**Post date:** [June 3, 2019, 12:28pm UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690/5 "2019-06-03T12:28:24Z")

</div>

Updated my code:

html file

```auto
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>
    <ion-title>Hospitals</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-searchbar (ionInput)="searchChanged($event)"></ion-searchbar>
  <ion-list *ngIf="results">
    <ion-item button *ngFor="let item of (information | async)" routerDirection="forward" [routerLink]="['/hospital-details/'+ item.id]">
      <ion-label text-wrap>
        <h3>{{ item.name }}</h3>
      </ion-label>
    </ion-item>
  </ion-list>

</ion-content>

```

ts file

```auto
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Routes, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { GetHospitalsService } from '../../services/get-hospitals.service';
import { SearchPipe } from './../../search.pipe';
import {filter, map} from 'rxjs/operators';

@Component({
  selector: 'app-hospitals',
  templateUrl: './hospitals.page.html',
  styleUrls: ['./hospitals.page.scss'],
})
export class HospitalsPage implements OnInit {

  // information = null;
  hospitals = null;
  searchTerm = '';

  results: Observable<any>;
  information: Observable<any>;

  constructor(private activatedRoute: ActivatedRoute, private hospitalService: GetHospitalsService, private router: Router) { }
  ngOnInit() {
    console.log('Hospitals enter');

    this.results = this.hospitalService.getHospitals1();
    this.information = this.filterArr2(this.searchTerm);

  }
  filterArr2(search): Observable<any> {
    console.log('enter the filterArr2');
    console.log('this.results', this.results);
    return this.hospitalService.getHospitals1().pipe(
          // map(oneObj => oneObj.name.toLowerCase().indexOf(search) > -1)
          map(data => data.filter(data.name.toString().toLowerCase().indexOf(search) > -1))
      );
  }

  searchChanged($event) {
    console.log('search changed entered');
    this.searchTerm = $event.target.value;
    console.log('search term passed', this.searchTerm);
    const mySearch = this.searchTerm.toLowerCase();
    console.log('search lower', mySearch);
    this.information = this.filterArr2(mySearch);
  }

}

```

I get the following error:

```auto
ERROR TypeError: Cannot read property 'toString' of undefined
    at MapSubscriber.project (hospitals.page.ts:37)

```

---

<div class="post-metadata">

**Author:** ![JohnCressman](https://avatars.discourse-cdn.com/v4/letter/j/c68b51/32.png) [@JohnCressman](https://forum.ionicframework.com/u/JohnCressman)\
**Post date:** [June 5, 2019, 12:45pm UTC](https://forum.ionicframework.com/t/having-a-hard-time-showing-filtered-observable/164690/6 "2019-06-05T12:45:29Z")

</div>

So I got it working. Here’s my code in case anyone else is having this issue.

json

```auto
{
  "hospitals": [ {
    "id": "1",
    "name": "Lehigh Valley Hospital-Cedar Crest",
    "address": "1200 South Cedar Crest Blvd, Allentown, PA 18105",
    "website": "www.lvhn.org",
    "trauma": "Level I",
    "peds": "Level II",
    "stroke": "Comprehensive",
    "ebola": "No",
    "phone": "610-402-8000",
    "special": "Special Annodote",
    "speciallink": "www.lvhn.org"
  },
    {
      "id": "2",
      "name": "Lehigh Valley Hospital-17th Street",
      "address": "17th and Chew Sts, Allentown, PA 18105",
      "website": "www.lvhn.org",
      "trauma": "N/A",
      "peds": "N/A",
      "stroke": "N/A",
      "ebola": "No",
      "phone": "610-969-2388",
      "special": "Special Annodote",
      "speciallink": "www.lvhn.org"
    },
    {
      "id": "3",
      "name": "Lehigh Valley Hospital-Mulenberg",
      "address": "2545 Schoenersville Rd, Bethlehem, PA 18017",
      "website": "www.lvhn.org",
      "trauma": "N/A",
      "peds": "N/A",
      "stroke": "Primary",
      "ebola": "Yes",
      "phone": "610-402-8000",
      "special": "Special Annodote",
      "speciallink": "www.lvhn.org"
    },
    {
      "id": "4",
      "name": "Lehigh Valley Hospital-Hazleton",
      "address": "700 East Broad St, Hazleton, PA 18201",
      "website": "hazleton.lvhn.org",
      "trauma": "N/A",
      "peds": "N/A",
      "stroke": "Primary",
      "ebola": "No",
      "phone": "570-501-4000",
      "special": "Special Annodote",
      "speciallink": "www.lvhn.org"
    }
  ]
}

```

html

```auto
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>
    <ion-title>Hospitals</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-searchbar placeholder="Search by Name" [(ngModel)]="searchTerm" (ionChange)="filterMe()"></ion-searchbar>
  <ion-list *ngIf="results">
    <ion-item button *ngFor="let item of (results | async)" routerDirection="forward" [routerLink]="['/hospital-details/'+ item.id]">
      <ion-label text-wrap>
        <h3>{{ item.name }}</h3>
      </ion-label>
    </ion-item>
  </ion-list>

</ion-content>

```

ts

```auto
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Routes, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { GetHospitalsService } from '../../services/get-hospitals.service';
import { SearchPipe } from './../../search.pipe';
import {filter, map, switchMap} from 'rxjs/operators';
import { FormControl } from '@angular/forms';
import {json} from '@angular-devkit/core';

@Component({
  selector: 'app-hospitals',
  templateUrl: './hospitals.page.html',
  styleUrls: ['./hospitals.page.scss'],
})
export class HospitalsPage implements OnInit {

  // information = null;
  searchTerm = '';
  searchText = '';

  data: any;
  results: Observable<any[]>;
  information: Observable<any[]>;

  myControl = new FormControl();

  constructor(private activatedRoute: ActivatedRoute, private hospitalService: GetHospitalsService, private router: Router) { }
  ngOnInit() {
    console.log('Hospitals enter');

    this.results = this.hospitalService.getHospitals1();
    this.information = this.results;
  }

  filterMe() {
    console.log('searchterm', this.searchTerm);
    this.searchText = '';
    if (this.searchTerm != null) {
      this.searchText = this.searchTerm.toLowerCase();
    } else {
      this.searchText = '';
    }

    this.results = this.information.pipe(
        map((reports: any[]) => reports.filter(p => {
          if (p.name.toString().toLowerCase().indexOf(this.searchText) > -1) {return p; }
        }))
    );

    console.log('results - after', this.results);

  }

}

```
