Как удалить определенный элемент из Observable <Array<any> >

Существует Наблюдение за множеством мест:

places: Observable<Array<any>>;

В шаблоне он используется с асинхронной трубой:

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

После некоторых действий пользователя мне нужно удалить место с определенным идентификатором из этого массива. В моем коде есть что-то подобное, но это не работает:

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

ты можешь помочь мне с этим?

Ответы

Ответ 1

Вы не можете сделать это так, потому что вы не можете "обновить" наблюдаемое (т.е. Не сохранять состояния), но вы можете реагировать на событие через него.

Для вашего случая использования я бы использовал оператора 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.

Ответ 2

Функция фильтра неизменна и не изменит исходный массив.

Я бы изменил функцию 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)
  );    
}