user11236708
user11236708

Reputation:

Angular RxJs - Crud Operations

public ngOnInit() {
  this.getUsers();
}

public getUsers() {
  this.userService.getUsers(this.listId).pipe(take(1)).subscribe(data => {
    if (data.result.length) {
      this.users = data.result;
    } else {
      const user = new UserModel();
      this.users = [user];
    }
    this.setupForm();
  });

}

public deleteUser(userId: number) {
  this.userService.delete(this.listId, userId)
    .subscribe(() => this.getUsers())
}

How would you recommand me, when I'm deleting an user from a table, to get back all the users? Is ok to call this.getUsers() method in .subscribe()? Or should I try to call it in .pipe()

Upvotes: 0

Views: 1202

Answers (2)

R. Salisbury
R. Salisbury

Reputation: 2006

I usually create an observable for getting data that updates whenever there's a CRUD operation. Here is a schematic example:

edit$ = this.editClick$
  .pipe(
     switchMapTo(this.latestFormValue$),
     switchMap(formValue => this.api.edit(formValue))
  )

delete$ = this.deleteClick$
  .pipe(
    switchMap(id => this.api.delete(id))
  )

getData$ = merge(this.edit$, this.delete$)
  .pipe(
    switchMap(() => this.api.getData(this.param))
  )

I will also say avoiding imperative and stateful code has been very helpful in reducing complexity and bugs. I only use state in components for the simplest things, such as a component with a single internal variable and one or two actions.

But even seemingly simple things like a breadcrumbs component that has inputs for navigation links have had race conditions that I had to fix by making it more reactive (in that case I got the inputs from route.params instead of the Inputs).

I would also avoid having any sort of body for subscribe. That is what the different operators are there for, and the operators make it clearer what you are intending as well as forcing you to think more reactively. If you really want to make users a state variable (I would recommend making it an observable and subscribing with AsyncPipe), then you should set it in a tap operator to make it obvious that you're introducing a side effect to the observable.

And in fact, if you set it up the way I've shown above and use AsyncPipe, you will not have to subscribe to any of those observables. AsyncPipe will subscribe to getData$ and getData$ will in turn subscribe to edit$ and delete$.

Upvotes: 2

Khumo Mogorosi
Khumo Mogorosi

Reputation: 411

It depends, if you want to get fresh data from the API every time you delete then you can use switchMap operator from import { filter, map, switchMap } from 'rxjs/operators';

Here is an example of how to use it:

public deleteUser(userId: number): void {
    this.userService
      .delete(this.listId, userId)
      .pipe(switchMap(() => this.userService.getUsers(this.listId)))
      .subscribe((res) => (this.users = res));
  }

Second solution would be removing the delete item from a list of users using javascript splice function:

    public deleteUser(userId: number): void {
            this.userService
              .delete(this.listId, userId)
              .subscribe((res) => {
            const index = this.users.findIndex(u => u.userId === userId);
            if (index > -1) {
                   this.users.aplice(index, 1)
            }
            });
          }

Upvotes: 1

Related Questions