1

I am new to ngrx / reactive pattern. I am trying to redesign some complex forms that we have from a template driven approach with component driven models to reactive forms using ngrx.

due to the way our api is written, some of the data from the form needs to be manipulated before posting the request to the server. In my old design, this was a somewhat complex function that I had to write with a ton of conditionals, but because everything was tied directly to the component itself, it was a straightforward approach to do the data manipulation, then subscribe to the endpoint

Now I am trying to use ngrx and ngx-formly for the form, so that I don't have to have multiple components and a ton of cluttered code, but I still need to manipulate the data before it hits the endpoint

Is there a way in ngrx effects for me to dispatch an action right before the http call?

I am still learning ngrx kind of on the fly, so only know the basic calls, but basically, need to know how I can make the form submission dispatch an action that would first call a reducer action to change the state, then right after the state has been updated, call an effect to send that data to the endpoint

Here is the reducer function I am trying to create

export const submitToRmv = (state: RmvServicesState, action) => {
    let vehicleArray = [...state.rmvData.rmvServicesUserEnteredData.vehicles];
    const transactionType = state.rmvData.transactionType;
    if (transactionType === 'PrefillRegistrationTransfer' || vehicleArray[0].reassignedPlate === 'Y') {
      const newVeh = {
        // modified codehere ... 
      };
      vehicleArray.push(newVeh);
      vehicleArray[0].plateNumber = '';
      vehicleArray[0].plateType = '';
    }
    vehicleArray = [...vehicleArray, ...state.rmvData.rmvServicesUserEnteredData.tradeInVehicles];

    const newTransactionType = transactionType === 'PrefillNewTitleAndRegistration' || transactionType === 'PrefillRegistrationTransfer' &&
    vehicleArray[0].reassignedPlate === 'Y' ? 'Reassign' : transactionType.replace('Prefill', '');

    return {
      ...state,
      rmvData: {
        ...state.rmvData,
        transactionType: newTransactionType,
        rmvServicesUserEnteredData: {
          ...state.rmvData.rmvServicesUserEnteredData,
          vehicles: vehicleArray,
        },
      },
    };

  };

I created a set of actions

export const validationSubmission = createAction(
'[Rmv Prefill Api] Rmv Validation Submission',
props<{getReadyRequest: RmvServicesData }>()

);

export const validationResponse = createAction(
    '[Rmv Prefill Api] Rmv Validation Response',
    props<{response: RmvValidationResponse }>()
);

my effect is to trigger that action

  rmvSubmit$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(RmvPrefillActions.validationSubmission),
      mergeMap((value) =>
      this.rmvService.getReadySubmit(value.getReadyRequest)
      .pipe(map(res => RmvPrefillActions.validationResponse({response: res}))
      )
    ));
  });

In my form, I am dispatching that action, and what I was hoping to happen was get the reducer function to execute the code to manipulate the data, then somehow, once it is finished, to then trigger the effect In my testing, it looks like the effect is triggering first, as the values being posted to my api is the unmodified data, then when I look at the redux dev tools, I do see that my values have changed, so reducer is working, just not in the order I want it to

Tom Yee
  • 69
  • 6
  • Way to broad. General flow is Action -> Reducer -> Effect. So the form can trigger the action, then the reducer would be invoked to change the state and finally the effect is called to hit the API. – Nicholas K May 11 '22 at 17:35
  • thank you for the response. yes, that is the flow I was trying to accomplish basically, my form on submission I am trying to get it to dispatch the action, which will trigger my reducer so I can get the state changed, but then I need to then have the effect kick in after that When I tried to create an action that will trigger the reducer and have an effect listen to that same action, it seems like it is doing the effect first, then the reducer – Tom Yee May 11 '22 at 18:26
  • Can't really help further until you've provided a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). Maybe you can add in a stackblitz link for the same as well. – Nicholas K May 11 '22 at 18:42
  • I added a snippit of code above that I am working with, basically the issue is trying to find out how to get my reducer first, then effect to trigger on the same button click. Do I need 2 separate actions, if so, still need to know how to get them to trigger in the correct order – Tom Yee May 11 '22 at 19:06

1 Answers1

0

yes, you need to do separate actions:

This is the style, I like to write my actions in:

export enum FormSubmissionTypes = {
GET_PRE_FORM_DATA = '[Rmv Prefill Api] pre form data',
GET_PRE_FORM_DATA_SUCCESS = '[Rmv Prefill Api] pre form data success',
DO_SOMETHING_WITH_DATA = '[Rmv Prefill Api] do something with data',
DO_SOMETHING_WITH_DATA_SUCCESS = ' do something with data success'
}

export const getData = createAction(
    FormSubmissionTypes.GET_PRE_FORM_DATA,
    props<{getReadyRequest: RmvServicesDataParams }>()
);

export const getDataSuccess = createAction(
    FormSubmissionTypes.GET_PRE_FORM_DATA_SUCCESS,
    props<{getReadyRequestResponse: RmvServicesDataResponse }>()
);

export const doSomething = createAction(
    FormSubmissionTypes.DO_SOMETHING_WITH_DATA,
    props<{getReadyRequest: RmvServicesDataResponse }>()
);

getData$ = createEffect(
    (): Observable<any> =>
      this.actions$.pipe(
        ofType(FormSubmissionTypes.GET_PRE_FORM_DATA),
        map((action: { getReadyRequest: RmvServicesDataParams }) => action.getReadyRequest),
        switchMap((getReadyRequest) =>
          this.service.fetchData(getReadyRequest).pipe(
            take(1),
            map((data: RmvServicesDataResponse[]) => getDataSuccess({getReadyRequestResponse:data }), doSomething({getReadyRequestResponse:data})
        )
      )
  );

Now you create an effect to deal with the success of the 'doSomething' action, the reducers will correspond when the actions are fired and the effects react to them. If you can create a stackblitz, I am happy to edit the code for you so it can work in this structure.

Kav Khalsa
  • 141
  • 3
  • 14