title: How to implement "Next" and "Previous" pagination with Angular + NgRx
body: <p>I am working on Angular project which uses NgRx to cache data. On a Submit button event, I need to fetch 20 records from server and display it. Now, I need to implement pagination(Next and Previous only) for next iteration. When I make a next request, I want to append the response to cache(NgRx store) so that I don't have to make request to backend for "Previous" page. In short, If cache already contains records, I don't want to make request to server. Where and how should I implement pagination logic? In a component or using Router Resolver?</p>
  
  <p>My current implementation(not working) is:</p>
  
  <pre><code>constructor(
    private store: Store&lt;AppState&gt;,
    private activatedRoute: ActivatedRoute,
    private router: Router
    ) {
    this.guestAds$ = this.store.select(guestAds); 
    this.activatedRoute.queryParams.subscribe((params: any) =&gt; {
     if (Object.keys(params).length) {
       this.queryParams = params;
       this.getAds();
     }
   });
  }
  
  onSubmit() {
    const form = this.searchForm.value;
    const queryParams = {
      searchTerm: form.searchTerm,
      category: form.category,
      subCategory: form.subCategory,
      limit: 20,
      startAt: 0,
      prevKeys: ''
    };
    this.router.navigate(['/'], { queryParams });
  }
  
  getAds() {
    this.guestAds$
      .pipe(
        tap(ads =&gt; {
          if (ads.length) {
            ads.forEach(ad =&gt; {
              if (ad.createdAt === Number(this.queryParams.startAt)) {
                console.log('Data alreadyd available');
                /* some logic */
              } else {
                this.store.dispatch(LoadAds({payload: this.queryParams}));
              }
            });
          }
        }),
      ).subscribe(/* I dont know if this is required?! */);
  }
  </code></pre>
  
  <p>My NgRx Effect looks like this:</p>
  
  <pre><code>loadAds$ = createEffect(() =&gt;
    this.actions$.pipe(
      ofType(GuestAdsActions.LoadAds),
      mergeMap((action) =&gt; this.guestAdsService.getAds(action.payload)
        .pipe(
          map((payload: any) =&gt; payload.data),
          map((payload: Ad[]) =&gt; GuestAdsActions.LoadAdsSuccess({ payload }),
          catchError(() =&gt; of(GuestAdsActions.LoadAdsSuccess({ payload: []}))
          )
        )
      )
    )));
  </code></pre>
  
  <p>My service looks like this:</p>
  
  <pre><code>getAds(queryParams: QueryParams) {
    console.log(queryParams);
    return this.http.get(`${this.BASE_URL}/ads`, { params: { ...queryParams } });
  }
  </code></pre>
  
  <p>I am calling getAds() method based on router query parameters change listener. What am I doing wrong? I would really appreciate if someone could help me on this. Thank you!</p>
  
  <p><strong>Edit</strong>: Added Effect and Service</p>