如何从Observable <array <any>&gt;中删除特定元素

时间:2016-07-04 10:04:45

标签: javascript typescript angular rxjs

有一个地方数组的Observable:

places: Observable<Array<any>>;

在模板中,它与异步管道一起使用:

<tr *ngFor="let place of places | async">
  ...
</tr>

在执行一些用户操作后,我需要从此数组中删除具有特定ID的位置。我的代码中有这样的东西,但它不起作用:

deletePlace(placeId: number): void {
  this.apiService.deletePlace(placeId)
  .subscribe(
    (res: any) => {
      this.places
        .flatMap((places) => places)
        .filter((place) => place.id != placeId);
    }, 
    (err: any) => console.log(err)
  );    
}  

你能帮我解决这个问题吗?

4 个答案:

答案 0 :(得分:20)

你不能这样做,因为你不能“更新”一个可观察的(即它不会保持状态),但你可以通过它对一个事件作出反应。

对于您的用例,我将利用scan运算符并将两个流合并为一个:

  • 一个用于初始加载
  • 另一个用于删除事件。

以下是一个示例:

let obs = this.http.get('/data').map(res => res.json());

this.deleteSubject = new Subject();

this.mergedObs = obs.merge(this.deleteSubject)
.startWith([])
.scan((acc, val) => {
  if (val.op && val.op==='delete') {
    var index = acc.findIndex((elt) => elt.id === val.id);
    acc.splice(index, 1);
    return acc;
  } else {
    return acc.concat(val);
  }
});

要触发元素删除,只需发送关于主题的事件:

this.deleteSubject.next({op:'delete', id: '1'});

请参阅此plunkr:https://plnkr.co/edit/8bYoyDiwM8pM74BYe8SI?p=preview

答案 1 :(得分:1)

过滤器功能是不可变的,不会改变原始数组。

我会将deletePlace函数更改为: -

deletePlace(placeId: number):  void {
  this.apiService.deletePlace(placeId)
  .subscribe(
    (res: any) => {
      this.places = this.places.filter((place) => place.id != placeId);
    }, 
    (err: any) => console.log(err)
  );    
}  

答案 2 :(得分:1)

您可以利用 filter 运算符:

this.places$
        .pipe(
            map(places => {
                // Here goes some condition, apply it to your use case, the condition only will return when condition matches
                return places.filter(place => place.placeId !== 0);
            }),
            map(response => (this.users$ = of(response)))
        )
        .subscribe(result => console.warn('Result: ', result));

答案 3 :(得分:1)

RxJS版本6

将接受的答案与 RxJS 6 typescript一起使用会引发错误,因为observables具有不同的类型。您最好使用combineLatest,也可以使用zip,但这将不起作用!你只是问为什么?答案是here:)

combineLatest([
  this.items$,
  this.deleteItem$
]).pipe(
  takeUntil(this.onDestroy),
  tap(([items, deleteItem]) => {
    if (deleteItem && deleteItem.op === 'deleteItem') {
      var index = items.findIndex((item) => item.id === deleteItem.id);
      if (index >= 0) {
        items.splice(index, 1);
      }
      return items;
    }
    else {
      return items.concat(deleteItem);
    }
  })
).subscribe();

然后您可以发送事件。

this.deleteItem$.next({ op: 'deleteItem', id: '5e88fce485905976daa27b8b' });

我希望它能对某人有所帮助。