angularrxjs

Filter observable without triggering HTTP request


I populate a grid with the following line of code:

this.gridData$ = this.userService.getUsers();

and this is the corresponding HTML:

[kendoGridBinding]="(gridData$ | async)!"

It works as expected.

I have also a delete button. Clicking the button deletes the user. After that I want to remove the user from the list, but withount making an extra HTTP request. I tried shareReplay, but the extra request is there:

this.gridData$ = this.gridData$.pipe(
              shareReplay({ bufferSize: 1, refCount: true }),
              map((users) => {
                return users.filter(
                  (user) => user.userId !== this.currentDataItem.userId
                );
              })
            );

How to filter the grid data in order to delete the deleted user without any extra HTTP request? Or should I store the users in a local variable on init, and modify the array upon adding, edit or delete and convert this to an observable?


Solution

  • Just add a deletedUsers property which is a BehaviorSubject, which stores the deleted users.

    We use combineLatest to filter the data, without re-fetching through the API. The changes in the deletedUsers behaviorSubject will trigger a recalculation.

      deletedUsers = new BehaviorSubject([]);
    
      this.gridData$ = combineLatest(
        this.userService.getUsers(),
        this.deletedUsers
      ).pipe(
        map((users: any, deletedUsers: any) => users.filter(
           (user) => !deletedUsers.includes(user.userId)
        ));
      );
    

    When you delete a user, push the ID to the deletedUsers behaviorSubject.

    this.deletedUsers.next([
      ...(this.deletedUsers.value() || []),
      1, // <--- deleted ID
    ]);
    

    NOTE: It is usually a good idea to refresh the list after CRUD operations, so that your end users do not work with stale outdated data.