Reputation: 1089
right now I have a resolver calling standard service and returning an Observable:
return this.someService.getData()
.map(data=> data.json())
I want to replace it with ngrx effects and store. When resolver is run I want to dispatch requestAction intercepted by effect, which makes http request. Once data is returned I dispatch dataReceivedAction with data as payload.
Basically i want to dispatch an action in resolver and wait till new data is in part of store. I try to do it this way:
return Observable.combineLatest(
Observable.of(
this.store.dispatch(new requestAction())
),
this.store.select(store => store.dataIWaitFor),
(dispatchedAction, dataArrived) => dataArrived
)
.skip(1)
it's not working, I mean the resolver doesn't render the component but when at the end of each of these returned Observables I add
.do(data => console.log(data))
the same data is logged. What I do wrong?
Upvotes: 3
Views: 3679
Reputation: 784
I tried to implement your solution in a resolver instead of a guard, it populates well my ngrx store, but the navigation is not done, I am stuck on the page where I call the route with resolver from. Also in the store we can see the data and router-store/requested and router-store/navigation but not router-store/navigated, neither router-store/cancel like when a guard blocks the navigation. Do you know what I miss and why nothing happends on the navigation side? I used the resolver in my route this way:
{
path: "params/users",
canActivate: [IsAdminGuard],
component: UsersComponent,
resolve: { usersLoaded: UsersResolver }
}
And here is the resolver, almost like your guard:
@Injectable()
export class UsersResolver implements Resolve<boolean> {
constructor(private store: Store<appState>) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
// API calls with ngrx effect
this.store.dispatch(usersActions.GET_USERS_TRY());
// Select users in store, switchMap(true) if array not empty
return this.store.pipe(
select(UsersSelectors.allUsers),
filter((allUsers: users[]) => allUsers.length > 0),
switchMap((allUsers: users[]) => return of(true))
);
}
}
Upvotes: 0
Reputation: 5598
You can do something like this
@Injectable()
export class SomeGuard implements CanActivate {
constructor(private store: Store<AppState>) {}
waitForDataToLoad(): Observable<Something> {
return this.store.select(state => state.something)
.filter(something => something && !something.empty);
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
this.store.dispatch({type: LOAD_something});
return this.waitForDataToLoad()
.switchMap(() => {
return Observable.of(true);
});
}
}
}
Upvotes: 2