Search code examples
angularngrxcanactivate

Using NGRX in Router Guard


Need some help with complicated Initialization using NGRX

I'm using a CanActivate guard for one of my routes to ensure my NGRX store is initialized with the necessary data for my component. I'm following the example in this post (https://stackoverflow.com/a/48652379/1568482) and building up from that.

Here's the Logic for my CanActivate Guard

  outputGrp$ = this.store.pipe(select(selectOutputGroup));
  inputGrp$ = this.store.pipe(select(selectInputGroup));
-----------------------------------------
return <Observable<boolean>>this.store.select(selectGroupsLoaded).pipe(
      map(loaded => {
        if(!loaded)
          this.store.dispatch(loadMainCanvas());
        return loaded;
      }),
      filter(loaded => !!loaded),
      take(1),
      withLatestFrom(this.outputGrp$), //Get Output Group ID
      tap(([loaded, og]) => this.outputGroupId = <string>og?.id),
      filter(loaded => !!loaded),
      take(1),
      map((data) => data[0]),
      withLatestFrom(this.inputGrp$), //Get Input Group ID
      tap(([loaded, ig]) => this.inputGroupId = <string>ig?.id),
      filter(([loaded, ig]) => !!loaded),
      take(1),
      //THIS NEVER GETS EVALUATED AGAIN AFTER STORE IS UPDATED FROM CALL BELOW!!!
      withLatestFrom(this.store.select(selectInputGroupProcessorsLoaded)), //See if Input Group Processors Loaded
      map(([l1, loaded]) => {
        if(!loaded)
          this.store.dispatch(loadProcessorsForGroup({groupId: this.inputGroupId, groupType: 'input'}));
        return loaded;
      }),
      filter(loaded =>!!loaded),
      take(1),
      // GET: ERROR Error: Uncaught (in promise): EmptyError: no elements in sequence
}

In my store, I store boolean values for each thing I want to test to see if the data is loaded. I'm evaluating those values here in the guard and if they aren't loaded, I dispatch a call to retrieve the data and update the store.

After the 'main canvas' item is loaded I progress and retrieve some necessary data for future calls here (groupIds). That data loads and I'm able to set variables with the necessary data.

When I get to withLatestFrom(this.store.select(selectInputGroupProcessorsLoaded)) it evaluates to FALSE and falls into the map() function. In there the store dispatches a call to retrieve the data and the store is successfully updated, BUT... the selectInputGroupProcessorsLoaded doesn't seem to change causing the statement to be re-evaluated.

I have a few more sections like this one and they all fail the same way.


Solution

  • So, switching out withLatestFrom to switchMap fixed my issue!