There is a simple (Angular 4) route guard, which waits for some data to be loaded from backend:
@Injectable()
export class ContractsLoadedGuard implements CanActivate {
constructor(private store: Store<State>) { }
waitForData(): Observable<boolean> {
return this.store.select(state => state.contracts)
.map(contractList => !!contractList)
.filter(loaded => loaded)
.take(1);
}
canActivate(): Observable<boolean> { return this.waitForData(); }
}
Routing:
const routes: Routes = [
{ path: 'app-list', canActivate: [ContractsLoadedGuard], component: AppListComponent },
];
And finally there is an @ngrx/effects triggered by @ngrx/router-store v4 ROUTER_NAVIGATION
action:
@Effect() routeChange$ = this.actions$
.ofType(ROUTER_NAVIGATION)
.filter((action: RouterNavigationAction) => action.payload.routerState.url.indexOf('/app-list') > -1)
.withLatestFrom(this.store.select(state => state.contracts))
.switchMap(([action, contracts]: ([RouterNavigationAction, ContractList])) =>
this.restClient.load(action.payload.routerState.queryParams, contract));
Unfortunatelly when navigation changes to /app-list
the ngrx effect is executed first (before guard) and thus the data state.contracts
are not available yet. The guard has not been executed yet.
I do have to add .combineLatest()
Rx operator to wait for the contracts
data in effect also (this is guard's job):
@Effect() routeChange$ = this.actions$
.ofType(ROUTER_NAVIGATION)
.filter((action: RouterNavigationAction) => action.payload.routerState.url.indexOf('/app-list') > -1)
.combineLatest(this.contractListGuard.waitForContractsToLoad(), a => a) <- HERE
.withLatestFrom(this.store.select(state => state.contracts))
.switchMap(/* same here */)
I'm not unsure if this is good solution enough. There must be a better way to do it - not duplicate the guard functionality in effect.
To summarize: On application boostrap, I need to fetch some data from backend - contracts
. If an user navigates to /app-list
(immediate redirect) there are other data fetched from server - based on some query params and contracts
- the ngrx router ROUTER_NAVIGATION
effect
execution order is before the guard execution order. How to handle this properly?
Based on GitHub - state_management_ngrx4