This subject is so big and important — especially the issue of reconciling redux-style (ngrx) store and the Angular router — that I am casting about for any guidance/input I can find. You seem to be an intelligent and critical person, so maybe you’ll be willing to tell me what holes see in the following grand solution. (No offense at all, of course, if you don’t wish to reply.):
To simplify, let’s take only the ‘talks’ route (TalkDetailsCmp), which requires talks data from the server db reflecting the current filter form input:
Consider the following flow:
1. User input (filters form properties) drives router navigation, adding the query as params (just as Victor does now):
handleFiltersChange(filters: Filters): void {
this.router.navigate([“/talks”, this.createParams(filters)]);
}
2. The router implements a route guard as a hook to dispatch an action requiring the HTTP GET, with an async boolean return to ultimately clear the guard if the query is successful. — like Victor does now — but with a more specialized type name:
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
…
this.lastState = state;
return this.store.sendAction({type: ‘QUERY_TALKS’, state});
}
3. Unlike Victor’s current approach, this action is handled *both* as an effect and by the reducer. The effect makes the HTTP request and maps the response as is presently done with backend.findTalks(filters). The reducer handles the QUERY_TALKS action by setting some kind of UI state property like isLoading = true so that components can consult it to run spinners or whatever.
When the backend.findTalks() successfully obtains the talks data from the server, the effect dispatches a new action (‘QUERY_SUCCESS’) with the talks data as payload, and this action is handled by the reducer, which
a. updates store.state
b. flips isLoading to false to kill spinners, etc.
c. nexts “true” to the subject observable that the route guard is waiting on to clear the route.
(Ignore error issues for now)
4. The TalkDetailsCmp component can consume the current state in one of two ways:
a. the conventional way (as it currently does) by tapping the injected store
get talks(): Talk[] {
return this.store.state.list.map(n => this.store.state.talks[n]);
}
OR
b. using resolvers that have been previously defined and provided to tap store.state (as in Victor’s router_mailapp github repo)
this.talks = route.params.pluck(‘talks’);
Any input at all would be greatly appreciated.