Search code examples
angularrxjsngrxngrx-effects

Rxjs in Ngrx - call action after filter/end of side effect


I'm using Angular 7 with the NGRX store. I have an effect, which will retrieve me some data if it doesn't exist in the store. I'm using the filter operator, but I always need to call an action, whether the data exists or not, at the end of the side effect. Here is my side effect (simplified):

getChartData$ = this.actions$
    .pipe(
        ofType(GET_CHART_DATA),
        withLatestFrom(this.store.pipe(select(x => x.store))),
        filter(((obj: [any, store]) => {
            return this.dataExistsInStore()
        })),
        map(obj => obj[0]),
        mergeMap((action) => this.chartService.getChartData((action as any).payload)
            .pipe(
                map((chartData: ChartData) =>
                    ({ type: GET_CHART_DATA_SUCCESS, payload: { tagId: (action as any).payload, chartData: chartData } })
                ),
                catchError(() => of({ type: GET_CHART_DATA_FAILED }))
            ))
    );

dataExistsInStore(): boolean
{
    return x;
}

How can I call an action even after the filter, e.g. an action of type GET_CHART_DATA_COMPLETE. I need to do this so I can hide the loading indicator.


Solution

  • If my understanding is correct, you would like to :

    • invoke getChartData only if data is not existing in store
    • dispatch an GET_CHART_DATA_COMPLETE action in all the case

    If that is true. You could consider this approach: (sorry, may have typos)

    getChartData$ = this.actions$.pipe(
      ofType(GET_CHART_DATA),
      withLatestFrom(this.store.pipe(select(isDataExistingInStore))),
      mergeMap(([action, isDataExistingInStore]: [Action, boolean]) => {
        if (!isDataExistingInStore) {
          return this.chartService.getChartData(action.payload).pipe(
            map((chartData: ChartData) =>
                    ({ type: GET_CHART_DATA_SUCCESS, payload: { tagId: (action as any).payload, chartData: chartData } })
                ),
            catchError(() => of({ type: GET_CHART_DATA_FAILED }))
          )
        } else {
          return of({ type: GET_CHART_DATA_COMPLETE })    
        };
      )
    )
    

    Here I'm considering, you have a selector : isDataExistingInStore, which return a boolean.

    Bonus: May I suggest you to use ngrx best practice to create actions:

    new GetChartDataSuccess(payload)
    

    or even better with action creators in version 8 :

    myActions.getChartDataSuccess({ tagId: .... });