【问题标题】:How to Filter Data coming from Firestore Database如何过滤来自 Firestore 数据库的数据
【发布时间】:2020-03-16 07:46:03
【问题描述】:

我想在我的代码上实现这个filtering,但我在实现它时遇到了问题。

FILTERING

我在执行这行代码时出错:

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);
  });
}

我无法更改 COUNTRIES.filter,当我尝试在其上放置/替换我的函数时出现错误。我收到此错误“属性'过滤器'不存在于类型'void'

这是我的代码。

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();
      })
    })
  }

我可以通过 sampleFunction() 从 firebase 获取所有数据。

顺便说一句,我使用以下代码在 html 上加载数据:

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

您能否帮我将我在 sampleFunction() 上获得的数据用于指南使用“return COUNTRIES.filter(country =&gt; {”行的搜索功能

【问题讨论】:

标签: javascript angular firebase google-cloud-firestore angularfire2


【解决方案1】:

您不会将 observable 全部返回到 async 管道。您正在执行手动订阅并映射结果。

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()))
  );
}

我建议尽可能向函数添加返回类型,Typescript 非常擅长发现像这样的基于类型的小错误。

现在的一个潜在问题是每次过滤器值更改时都会调用this.extractorService.dbFirestore()。如果您不希望这种情况发生,您需要一种不同的方法。

使用静态数据

您可能只想先加载数据,然后过滤固定数组。在这种情况下,您将首先加载数据,然后将值更改链接到 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()))
  );
}

那么您的 HTML 将观看 filteredCountries$ 而不是 countries

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

【讨论】:

  • 感谢 Kurt... 在进行这些更改后。它现在终于可以工作了……关于调用 this.extractorService.dbFirestore() 的问题,您对如何避免它有什么建议吗?谢谢
  • 我已经更新了我的答案。只要您考虑可观察对象,它就相当简单。你想先获取数据,然后你想开始观察值的变化
  • 嗨,Kurt... 现在我有一个问题,每当数据库发生更改(添加、删除、更新)时,表都不会重新加载/更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-26
  • 2021-11-24
  • 2020-07-23
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 2021-01-12
相关资源
最近更新 更多