可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
There is an Observable of the array of places:
places: Observable<Array<any>>;
In template it used with the async pipe:
<tr *ngFor="let place of places | async"> ... </tr>
After some user actions I need to remove the place with specific id from this array. I have something like this in my code, but it doesn't work:
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) ); }
Can you help me with this?
回答1:
You can't do it this way since you can't "update" an observable (i.e. it doesn't keep states) but you can react to an event through it.
For your use case, I would leverage the scan
operator and merge two streams into a single one:
- one for the initial loading
- another one for the delete event.
Here is a sample:
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); } });
To trigger an element deletion, simply send an event on the subject:
this.deleteSubject.next({op:'delete', id: '1'});
See this plunkr: https://plnkr.co/edit/8bYoyDiwM8pM74BYe8SI?p=preview.
回答2:
The filter function is immutable and won't change the original array.
I would change the deletePlace function to something like this:-
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) ); }