I'm working on the Angular guard with @ngrx/store to check if state has been already loaded and I faced an issue that canActivate method never returns if I use filter.
Here is an example effect for GetCompanies action:
return this.companiesService.getCompanies()
.pipe(
map(companies => new companiesActions.GetCompaniesSuccess(companies)),
catchError(error => Observable.of(new companiesActions.GetCompaniesFail(error)))
)
If there is an error I'm dispatching a GetCompaniesFail action and redirect a user to /login page. That's fine, the interesting part is with the guard.
@Injectable()
export class CompaniesGuard implements CanActivate {
constructor(
private store: Store<AppState>,
private router: Router
) {}
canActivate(): Observable<boolean> {
return this.checkStore()
.pipe(
switchMap(() => Observable.of(true)),
catchError(() => Observable.of(false))
);
}
checkStore(): Observable<boolean> {
return this.store.select(getCompaniesLoaded)
.pipe(
tap(loaded => {
if (!loaded) {
this.store.dispatch(new companiesActions.GetCompanies());
}
}),
filter(loaded => loaded),
take(1)
);
}
}
If there is an error and loaded is not false, canActivate wouldn't return anything because checkStore does nothing.
If I change filter to map it works but it takes only the first value which is false even if the data will be loaded successfully.
What am I missing? How can I handle HTTP errors there? Is there a way to either wait for certain state or throw an error inside checkStore?
Thank in advance!
canActivateto emit false? - bygrace