0

I am having an issue with my canActivateChild route guard not waiting for data to come back from 3 service calls to the backend before determining whether it can activate the route or not. I have it hooked into the ngRx store and am dispatching 3 separate actions, and then using forkJoin to return what I thought would be an Observable as to whether they all return data or not. This doesn't seem to be working properly because one of the 3 usually returns undefined in the component.

As far as I understand the select returns an observable and the filter/take(1) ensures the observable completes once the condition is met. This seems to be working properly as it hits multiple times in the filter, eventually having data for 2 of them. I don't understand why it would return true if one of the items returns no data.

Any help as to how to get this working properly?

getFromStoreOrAPI(): Observable<any> {
   return forkJoin(
      this.store.select(getFinancialFactors).pipe(filter(financialFactors => financialFactors && financialFactors.length > 0), take(1)),
      this.store.select(getFinancialData).pipe(filter(financialData => financialData && financialData.length > 0),take(1)),
      this.store.select(getFranchiseData).pipe(filter(franchiseData => franchiseData && franchiseData.length > 0),take(1))
   );
}

canActivateChild(route: ActivatedRouteSnapshot): Observable<boolean> | boolean {
    let tranId = this.router.getCurrentNavigation().extras.state.tranId;
    let modelId = this.outer.getCurrentNavigation().extras.state.modelId;

    this.store.dispatch(ScorecardActions.loadFinancialData({tranId: tranId}));
    this.store.dispatch(ScorecardActions.loadFranchiseData({tranId: tranId}));
    this.store.dispatch(ScorecardActions.loadFinancialFactors({modelId: modelId}));

    return this.getFromStoreOrAPI()
    .pipe(
        switchMap(() => of(true)),
        catchError(() => of(false))
     );
   }
}
MattE
  • 1,044
  • 1
  • 14
  • 34
  • i believe if one item has no data it will return empty observable, not "of(true)" in your case. just no events comes from `getFromStoreOrAPI()` – Andrei Sep 02 '20 at 23:51
  • also are you sure you need `canActiveChild`, not just `canActivate` guard in your case? could fix the problem – Andrei Sep 02 '20 at 23:54
  • @Andrei yes, the guard is on the parent for the child routes, so it should be canActivateChild. Also, shouldn't the filter prevent the observable from completing with no data since take(1) will not run and therefore not complete the Observable? – MattE Sep 02 '20 at 23:55
  • does loadFinancialData and other load action always spawn a http request? – Andrei Sep 02 '20 at 23:59
  • @Andrei yes, 3 separate HTTP calls are made via 3 separate services to a Controller on the backend(ASP.NET) which all end up hitting the same SQL Server DB. – MattE Sep 03 '20 at 00:07
  • you could try `select(...).pipe(skip(1), take(1))` for each of data sources and return true when all of the data is returned – Andrei Sep 03 '20 at 00:08
  • @Andrei same thing happens...doesn't really make any difference it seems – MattE Sep 03 '20 at 00:27
  • could there anything else except for this guard cause data erase or refetch? I believe your guard gets the data and then it is lost at some point – Andrei Sep 03 '20 at 00:30
  • No, that is the only place where a dispatch is called for this – MattE Sep 03 '20 at 00:31
  • could that be that this guard and child component inject different instances of State? – Andrei Sep 03 '20 at 00:32

0 Answers0