简体   繁体   English

从 Angular Firestore 过滤 Observable

[英]Filtering an Observable from Angular Firestore

I have seen some answers to this that apply the filter to the database call.我已经看到了一些将过滤器应用于数据库调用的答案。 I only need to call the database once but can't work out how to filter the array that is inside the observable returned by Firebase.我只需要调用数据库一次,但无法弄清楚如何过滤 Firebase 返回的可观察对象内的数组。

I have 2 select boxes with a list of tags.我有 2 个带有标签列表的选择框。 I want to get the whole set of items from Firestore and store it in the items Observable.我想从 Firestore 获取整套项目并将其存储在项目 Observable 中。 Then when one of the select boxes changes I want to filter that observable so only the items with those tags are shown.然后,当其中一个选择框发生变化时,我想过滤该 observable,以便只显示带有这些标签的项目。

items: Observable<any[]>;
  selectedTag1;
  selectedTag2;

  filteredItems: Observable<any[]>;

  tagName1 = ['', 'TAG1', 'TAG2', 'TAG3', 'TAG4'];
  tagName2 = ['', 'TAG5', 'TAG6', 'TAG7',

  constructor(db: AngularFirestore) {
  this.items = db.collection('items').valueChanges();
  }

  ngOnInit() {
    this.filteredItems = this.items.pipe(
      map((arr => arr.filter(item =>
        item.tags.some(s => s === this.selectedTag1) &&
        item.tags.some(s => s === this.selectedTag2))
        )));
  }

I get no items at all showing on my template.我的模板上根本没有显示任何项目。 When I change the selectedTag using the select box.当我使用选择框更改 selectedTag 时。 I also get no filtering of the items.我也没有过滤项目。 Can somebody suggest how I do this correctly.有人可以建议我如何正确地做到这一点。 I need the selectBoxes to filter if only one has a value or if both have a value.我需要 selectBoxes 来过滤是否只有一个值或两者都有值。

HTML HTML

<select [(ngModel)]="selectedTag1">
  <option  *ngFor="let item of tagName1">{{ item }}</option>
</select>

<select [(ngModel)]="selectedTag2">
  <option  *ngFor="let item of tagName2">{{ item }}</option>
</select>

<ul>
  <li class="text" *ngFor="let item of filteredItems | async">
    {{item.name}}
    <ul>
      <li *ngFor="let tags of item.tags">
        {{tags}}
      </li>
    </ul>
  </li>
</ul>

ITEMS项目

[
  {
    "name": "Item 1",
    "tags": [
      "TAG1",
      "TAG4",
      "TAG5",
      "TAG6"
    ]
  },
  {
    "name": "Item 2",
    "tags": [
      "TAG2",
      "TAG3",
      "TAG5",
      "TAG7",
    ]
  }
]

I have tried to add a function which runs when the select box is changed.我试图添加一个在选择框更改时运行的函数。

selectChanges() {
    this.filteredItems = this.items.pipe(
      map((arr => {
        console.log(arr);
        console.log(this.selectedTag1);
        arr.filter(item => {
        console.log(item.tags);
        item.tags.some(s => s === this.selectedTag1);} );
      })));
  }

Yet I am still not getting any filtered results.但是我仍然没有得到任何过滤结果。

As you already guessed, you should not filter when selected tags is undefined or empty.正如您已经猜到的,您不应在所选标签未定义或为空时进行过滤。 Just tweak your filtering logic as shown below:只需调整您的过滤逻辑,如下所示:

  filter() {
    this.filteredItems = this.items.pipe(
      map(arr =>
        arr.filter(item => {
          // return true if selectedTag1 or selectedTag2 is empty

          const matchesForTagName1 = this.selectedTag1
            ? item.tags.indexOf(this.selectedTag1) >= 0
            : true;
          const matchesForTagName2 = this.selectedTag2
            ? item.tags.indexOf(this.selectedTag2) >= 0
            : true;
          return matchesForTagName1 && matchesForTagName2;
        })
      )
    );
  }

You can view the complete example in Stackblitz here .您可以在此处查看 Stackblitz 中的完整示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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