Handling successful action dispatch in component

Viewed 3605

I have a component with a form that adds items to a list. After successfully adding an item to the list, I want to use form.resetForm();, but I can't figure out a simple way to know when that action was successful. I was hoping I could subscribe to the action dispatch, but haven't been able to figure that out.

I've tried several approaches I've found online, but they all seem to be outdated. I did get it to work by adding a saving property to my store and subscribing to that, but that seemed like an excessive amount of work for something that should be pretty simple.

Is there a way to just subscribe to something inside my component or container without refactoring my NGRX logic?

Here is the code in my container that adds the item to the list:

addPosition(position: Position) {
  this.store.dispatch(new fromStore.CreatePosition(position));
}

Action:

export const CREATE_POSITION = '[Profile] Create Position';
export const CREATE_POSITION_FAIL = '[Profile] Create Position Fail';
export const CREATE_POSITION_SUCCESS = '[Profile] Create Position Success';

export class CreatePositionSuccess implements Action {
  readonly type = CREATE_POSITION_SUCCESS;
  constructor(public payload: any) {}
}

Effect:

@Effect()
    createPosition$ = this.actions$.pipe(
        ofType(positionsActions.CREATE_POSITION),
        map((action: positionsActions.CreatePosition) => action.payload),
        switchMap(position => {
            return this.positionService
                .addPosition(position)
                .pipe(
                    map(newPosition => new positionsActions.CreatePositionSuccess(newPosition)),
                    catchError(error => of(new positionsActions.CreatePositionFail(error)))
                );
        })
    );

I'm on version 7 of ngrx and 6.3 of rxjs.

1 Answers

You can inject the Action service into your component and then subscribe to it in order to listen when you dispatch the "CreatePositionSuccess" action.

For instance, in your component:

import { Actions } from '@ngrx/effects';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class SampleClass implements OnInit, OnDestroy {
  private unsubscribe$ = new Subject<void>();

  //Injecting the service
  constructor(private actions$: Action){}

  onInit() {
    this.actions$
    .pipe(
      ofType<CreatePositionSuccess>(CREATE_POSITION_SUCCESS),
      // You can add more operator if it is necessary into the observable.
      takeUntil(this.unsubscribe$)
    )
    .subscribe(() => {
      // Here you can execute the reset function
    });
  }

  onDestroy() {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}

With that, you will be able to reset the form immediately the success action is called.

By the way, the "unsubscribe" Subject is used to automatically unsubscribe from the Observable when the component is destroyed in order to avoid memory leaks. You can notice how I used it into the on destroy method.

Related