简体   繁体   中英

How to Filter Data coming from Firestore Database

I want to implement this filtering on my code, but I have an issue in implementing it.

FILTERING

I' having an error in implementing this lines of codes:

function search(text: string, pipe: PipeTransform): Country[] {
  return COUNTRIES.filter(country => {
    const term = text.toLowerCase();
    return country.name.toLowerCase().includes(term)
        || pipe.transform(country.area).includes(term)
        || pipe.transform(country.population).includes(term);
  });
}

I can't change the COUNTRIES.filter , I'm getting an error when I try to put/replace my function on it. I get this error " Property 'filter' does not exist on type 'void' "

Here's my code.

export class MyComponent implements OnInit {

  countries: Observable<any[]>;
  filter = new FormControl('');

  listQuestions = [];


  constructor(private extractorService: ExtractorService, 
              private fstore: AngularFirestore) { }

  ngOnInit() {
   this.filterFunction();
  }

  filterFunction(){
    this.countries = this.filter.valueChanges.pipe(
      startWith(''),
      map(text => this.search(text))
    );
  }

  search(text: string): any[] {
    return this.sampleFunction().filter(country => {
      const term = text.toLowerCase();
        return country.caseID.toLowerCase().includes(term)
            || (country.word).toLowerCase().includes(term)
            || (country.product).toLowerCase().includes(term);
    });
  }

  sampleFunction() {
    this.extractorService.dbFirestore().subscribe(data => {
      this.listQuestions = data.map(x => {
        return x.payload.doc.data();
      })
    })
  }

I can get all the data from firebase from my sampleFunction() .

BTW I load the data on html using this codes:

<tr *ngFor="let item of countries | async">

Can you please help me to use the data that I get on my sampleFunction() to the search function in where the guide use the lines " return COUNTRIES.filter(country => { "

You're not returning the observable all the up to the async pipe. You're performing a manual subscription instead and mapping the results.

filterFunction() {
  this.countries = this.filter.valueChanges.pipe(
    startWith(''),
    switchMap(text => this.search(text))
  );
}

search(text: string): Observable<any[]> {
  return this.sampleFunction().pipe(
    map(countries => {
      return countries.filter(country => {
        const term = text.toLowerCase();
        return country.caseID.toLowerCase().includes(term)
          || (country.word).toLowerCase().includes(term)
          || (country.product).toLowerCase().includes(term);
      });
    });
  );
}

sampleFunction(): Observable<any[]> {
  return this.extractorService.dbFirestore().pipe(
    map(data => data.map(x => x.payload.doc.data()))
  );
}

I would recommend adding return types to functions wherever possible, Typescript is great at finding small type-based mistakes like this.

One potential issue now is that this.extractorService.dbFirestore() is going to be called every time the filter value changes. If you don't want this to happen you need a different approach.

Working with static data

You probably just want to load the data first and then filter a fixed array. In which case, you would load the data first and then chain the value changes onto that with a concatMap .

filteredCountries$: Observable<any[]>;
private countries: any[];

filterFunction() {
  // load the countries first
  this.filteredCountries$ = this.getCountries().pipe(
    // set the countries
    tap(countries => this.countries = countries),
    // now start observing the filter changes
    concatMap(countries => {
      return this.filter.valueChanges.pipe(
        startWith(''),
        map(text => this.search(text))
    })
  );
}

search(text: string): any[] {
  return countries.filter(country => {
    const term = text.toLowerCase();
    return country.caseID.toLowerCase().includes(term)
      || (country.word).toLowerCase().includes(term)
      || (country.product).toLowerCase().includes(term);
  });
}

getCountries(): Observable<any[]> {
  return this.extractorService.dbFirestore().pipe(
    map(data => data.map(x => x.payload.doc.data()))
  );
}

Then your HTML would be watching filteredCountries$ instead of countries .

<tr *ngFor="let item of filteredCountries$ | async">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM