2

I am trying to implement ion search bar in the following way

My HTML page is

 <ion-searchbar (ionInput)="getFilteredItems($event)"></ion-searchbar>
   <button ion-item *ngFor="let patient of surveyPatients | async" (click)="showPatientData(patient)">{{patient.name}} - {{patient.age}} - {{patient.idCardNumber}}</button>

Corresponding ts file,

 surveyPatients:any;
getFilteredItems(ev: any) {
    this.initializeSurveyPatients();

    let val = ev.target.value;
    alert(val);
    console.log(this.surveyPatients.length);
    if (val && val.trim() != '') {
      this.surveyPatients = this.surveyPatients.filter((item) => {
        //alert(item.name);
        return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
      })
    }
  }


initializeSurveyPatients() {

        this.surveyPatients = this.afoDatabase.list('/SurveyPatients',
      {
        query:{
              orderByChild: 'district',
              equalTo: 'Nalgonda '
            }
      }

      );


  }

When I see alert(val) I am getting the what ever the input that is entered in the search box. But when I try console.log(this.surveyPatients.length); I am getting undefined. That is the reason why I am getting Cannot read property 'toLowerCase' of undefined Error.

In the constructor I am running this.initializeSurveyPatients(); Hence I am able to see the data in the front end on page load.

Why I am not able to read the collection this.surveyPatients inside the getFilteredItems method?

Updated Code

    initializeSurveyPatients() {

            this.afoDatabase.list('/SurveyPatients',
          {
            query:{
                  orderByChild: 'district',
                  equalTo: 'Nalgonda '
                }
          }

          ).subscribe(snap => {

          this.surveyPatients = snap;

        });
 getFilteredItems(ev: any) {

    //this.initializeItems();
    this.initializeSurveyPatients();

    let val = ev.target.value;
    console.log(this.surveyPatients.length);

    if (val && val.trim() != '' ) {

      this.surveyPatients = this.surveyPatients.filter((item) => {
               return (item.name.toLowerCase().indexOf(val.toLowerCase()) > -1);
      })
       console.log(this.surveyPatients.length);
        }
      }


      }

Corresponding html code

<button ion-item *ngFor="let patient of surveyPatients" (click)="showPatientData(patient)">{{patient.name}} - {{patient.age}}
- {{patient.idCardNumber}}</button>

Note: I removed async filter

In this case, I am able to get correct values for console.log(this.surveyPatients.length); before filter and after filter as expected, inside getFilteredItems method. Which confirms us the filter is working.

The only issue is values In the UI are not updating after the filter.

vjnan369
  • 833
  • 16
  • 42
  • Probably because `initializeSurveyPatients` is async. `this.surveyPatients` is not yet defined when you try to access it. – David Oct 07 '17 at 20:49

2 Answers2

1

Since that is observable you need to subscribe it to return a value.

Note: Refactor the code as you wish.This is just a concept.

this.afoDatabase.list('/SurveyPatients',
      {
        query:{
              orderByChild: 'district',
              equalTo: 'Nalgonda '
          } }
      ).subscribe(snap => {

      this.surveyPatients = snap;//here

    });
Sampath
  • 63,341
  • 64
  • 307
  • 441
  • Thanks for the answer. When I try this, I am able to read the item.name property but filter is not working. Also I have to remove async pipe in the front end code. What can be wrong? – vjnan369 Oct 08 '17 at 04:47
  • Can you show your latest `code`? Put that on the separate section on your question above. – Sampath Oct 08 '17 at 05:03
  • Can you see this article: https://www.joshmorony.com/high-performance-list-filtering-in-ionic-2/ – Sampath Oct 08 '17 at 06:42
  • Actually I am getting expected value for item.name.toLowerCase().indexOf(val.toLowerCase()) also. The only thing that I did not understand is why that filter is not working. Is it mandatory to have data provider? – vjnan369 Oct 08 '17 at 07:12
  • What did you mean by `data provider` here? – Sampath Oct 08 '17 at 07:16
  • In the link you have shared, they have used separate data service to manage/filter data. – vjnan369 Oct 08 '17 at 07:24
  • Yes, That is good coding practice to maintainable code. We need to follow that. – Sampath Oct 08 '17 at 07:25
0

One reason for getting this error could be that item.name is undefined at the time you try to perform this function.

Try to use some protection like:

if item.name.type === 'string'

You can also try to use the Elvis operator:

item.name?.toLowerCase()

Udi Mazor
  • 1,646
  • 2
  • 15
  • 30