0

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?

3 Answers 3

1

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.

0

Building on Naren Murali's answer. It might be best to give the service full ownership over the user data. Right now it looks like the service just gets the data, then it belongs to the component. Changing your service to be something like the following might help:

export class UserService {
  private deletedUserIdsSubject = new BehaviorSubject<number[]>([]); // list of user IDs that have been deleted

  public users$: Observable<User[]> = // public users observable that your components can use
    combineLatest([this.getUsers(), this.deletedUserIdsSubject]).pipe(
      map(([users, deletedUserIds]) => users.filter(user => !deletedUserIds.includes(user.id))) // filter out deleted users
    );

  public deleteUser(userId: number) {
    this.deletedUserIdsSubject.next([userId, ...this.deletedUserIdsSubject.getValue()]);
  }

  private getUsers(): Observable<User[]> { // make this private so that only the service can decide when to get fresh data
    // ...
  }
}

Your component could then use this.userService.user$ and this.userService.deleteUser() to interact with the user data, while keeping allowing the service to be in charge of the users. You can also add additional methods to the service to support features like adding, filtering, and pagination. This approach is good because keeps the details of how/when the users are retrieved out of the component. If you need to change the logic later, the component doesn't care if the service refreshes from the server or does an in-memory delete, or find some other method. Those details are the service's problem, not the component's.

-1
public readonly users = signal([]);

public ngOnInit(): void { 
  this.fetchUsers();
}

private fetchUsers(): void {
  this.userService.getUsers().pipe(take(1)).subscribe((data) => {
    this.users.set(data);
);
}

private onDeleteSuccess(userId: number): void {
 const filteredUsers = this.users()?.filter((user) => user.userId !== userId);

 this.users.set(filteredUsers);
}

and on HTML:

[kendoGridBinding]="users()"
1
  • I was not the downvvoter, but if you add some details, then it sounds as a good idea.
    – akop
    Commented Apr 21 at 21:46

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.