Home > database >  Delete Elements from Observable after everything has rendered in RxJS
Delete Elements from Observable after everything has rendered in RxJS

Time:09-28

So lets say i retrieve entries from a backend and display those in a table. Now, the user wants to delete entries by clicking on a button.

The entry must be deleted server-side and the ui should reflect the change. I do not want to reload all entries from the backend but rather remove the deleted entry from the model based on which the table is rendered (entries$).

I tried the following:

    deleteEntrySubject = new BehaviorSubject<any>(null);
    deletedEntry$ = this.deleteEntrySubject.asObservable();
    //.pipe(switchMap(e => this.entryService.delete(e)));
    
    entries$ = combineLatest([
      of([
        { n: '1', id: 1 },
        { n: '2', id: 2 },
      ]),
      this.deletedEntry$,
    ]).pipe(
        filter(([entries, deletedEntry]) => deletedEntry !== null),
        map(([entries, deletedEntry]) =>
          entries.filter((entry) => entry.id !== deletedEntry?.id)
        )
      )
      .subscribe((result) => console.log('res', result));
    
    deleteEntry(id) {
      this.deleteEntrySubject.next({ n: id, id: id });
    }

Which works very well - BUT since the initial observable (here provided by of()) didn't change it will start with the same two values every time. So when o delete entry 1, i will have entry 2 in the result, when i then delete entry 2 i will get entry 1 in the result (which should not appear anymore since it was deleted previously.

I understand that Observables can not "change" - but at the same time i don't know how to make this happen the rxjs way without having to use some component state to remember which entries have already been deleted.

So whats the move here? How do i make it "right"?

The code above is available here: https://stackblitz.com/edit/angular-ivy-dibess?file=src/app/hello.component.ts

CodePudding user response:

You can store the data that you received from the server in a local store (entries$ = new BehaviorSubject<any[]>([])) within the component (Ideally, this should be stored in a Service/Store...etc not in the component). Then you can update/emit the source of this store each time you want to delete from or update it, like the following:

entries$ = new BehaviorSubject<any[]>([]);

get entries() {
  return this.entries$.value;
}

ngOnInit() {
  this.fetchData();
}

fetchData() {
  this._mockHttpGet().subscribe((res) => this.entries$.next(res));
}

deleteEntry(id) {
  const newEntries = this.entries.filter((item) => item.id !== id);
  this.entries$.next(newEntries);
}

/** Mock of you HTTP request */
private _mockHttpGet(): Observable<any[]> {
  return of([
    { n: '1', id: 1 },
    { n: '2', id: 2 },
  ]);
}

And here is a working StackBlitz version with the desired changes.

  • Related