Search code examples
angularngrxstore

How to Implement NgRx Effect to Conditionally Trigger Modal Based on Product Price?


I want to check if the cost of the product is over 10 using NgRx state management. Then, if the product value is over 10 I want to show the

sval 

(sweetalert) element.

I have this code in reducer.ts:

public interface IProductsList{
  items: IProductListItem[]
}

public interface IProductListItem{
  price: int;
  name: string
}

So I create actions:

export const openPriceModal = createAction('[Products]')
export const openPriceModalSuccess = createAction('[Products]')
export const openPriceModalFailed = createAction('[Products]')

In the reducer I have these selectors:

export interface IProductsRequestState {
  selectedItem: IProductListItem
  list: IProductsList
}
export const getSelectedProductsRequestList = createSelector(getSelectedProductsRequestList , state => state.list)
  export const getSelectedProductsRequest = 
  createSelector(getSelectedProductsRequest, state => state.selectedItem )

Now I want to write an effect.ts that opens a modal depending on the prices:

openPriceModal = createEffect(() => 
  this.action$.pipe(ofType(openPriceModal), withLatestForm(() => {
..
})))

If it wasn't for store management, I would write it like this:

  1. Get the list of items

  2. Iterate through the list of this item and compare the price property

  3. Return an element based on the result

I don't know how to implement this using NgRx.

All the logic has to be inside NgRx, and no logic should be in the component.


Solution

  • You can use selector to achieve just that. So you can create a custom selector that check if the cost of the product is over 10 or not.

    Example:

    // selector.ts

    export const getSelectProductOver10 = createSelector(
      getSelectedProductsRequestList,
      (product) => product.items.length > 10,
    );
    

    // effect.ts

      openPriceModal = createEffect(
        () =>
          this.action$.pipe(
            ofType(openPriceModal),
            withLatestFrom(this._store.pipe(select(getSelectProductOver10))),
            map(([, isOver10]) => {
              if (isOver10) {
                // call the service to open the modal (sweetalert)
                ....
              }
           .....