过滤嵌套对象数组-可观察

时间:2019-03-15 00:49:04

标签: angular rxjs observable rxjs6

我有一个包含对象对象的数组的可观察对象。 (如图所示)。我有一个observable,它从get请求中接收这些值,然后又有另一个observable用于存储过滤后的值。我有一个binded到一个input的searchText变量,每次输入更改时我都会调用一个函数。

 <input name="problem-search" [(ngModel)]="searchText" matInput placeholder="Search for problems..." (input)="filterProblems()">

到现在为止,我已经尝试过了,但是没有产生期望的输出。它有时会进行过滤,但这是随机的,甚至与searchInput不相关。坦率地说,我什至不知道我是如何获得输出的。 Rxjs有时会令人困惑。请让我知道我在这里做错了什么。enter image description here

    filterProblems() {
    if (this.searchText === '') {
      this._filteredProblems$ = this._everyProblem$;
    }

    this._filteredProblems$ = this._everyProblem$.pipe(
      map(data => data),
      tap(ele => ele.filter(data => {
        Object.keys(data).forEach(key => {
          if (data[key].name.toLowerCase().includes(this.searchText)) {
            delete data[key];
          }
        });
      }))
    );

    this._filteredProblems$.subscribe(data => console.log(data))
  }

1 个答案:

答案 0 :(得分:0)

tap operator应该用于产生副作用,并不意味着它是流修改操作。以这种方式使用map operator实际上并没有为您做任何事情。我认为您应该从map样式运算符之类返回已过滤的对象,以更改流返回的内容,而不是原始对象。当前,整个对象将返回到流中,减去您从其中删除的键。删除后,它们似乎会从原始文件中删除。

使用Object.keys是一种能够遍历对象的方法,但是在这种情况下,您可以使用Object.values保存一个步骤,然后从结果中拉出您想要的键。

类似这样的东西应该接近您的需求:

map((data: yourType[]) =>
  data.filter((item: yourType) =>
    (!this.searchText || !Object.values(item)[0].name.toLowerCase().includes(this.searchText))
),
  • 从data.filter返回结果至少会给您一个空数组,前提是原始数据至少是一个空数组。
  • 反转searchText的flasy值将返回所有项
  • Object.values将返回来自Guid的对象列表
  • [0]将返回第一个(应该是一个)
  • 返回include的倒数将保留不包含搜索文本的项目

或者,您可以设置触发流以查看源数据或输入是否发生更改。  -将searchText放在BehaviorSubject中,以便您可以使用它来触发流中的更改。  -将searchText observable和_everyProblem $ observable与CombineLatest结合使用,并将结果设置为_filteredProblems $  -在内部应用类似的过滤器,以及去抖动

可能与此类似的东西引起了一些思考:

this._filteredProblems$ = combineLatest(
  this.searchTextSubject.asObservable(),
  this._everyProblem$,
).pipe(
  debounce(() => timer(50))
  map((searchText: string, data: yourType[]) =>
    data.filter((item: yourType) =>
      (!searchText || !Object.values(item)[0].name.toLowerCase().includes(searchText))
  ),
);