So, i trying to follow ngrx/example-app and i stacked with router guards. My guard doesn't work.
import 'rxjs/add/operator/take';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/let';
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { Action } from '@ngrx/store';
import * as fromRoot from '../reducers';
import * as playlists from '../actions/playlists';
@Injectable()
export class PlaylistsExistsGuard implements CanActivate {
constructor(
private store: Store<fromRoot.AppState>,
private router: Router
) {}
waitForCollectionToLoad(): Observable<boolean> {
return this.store.select(fromRoot.getPlaylistsLoaded)
.filter(loaded => loaded)
.take(1);
}
hasPlaylistsInStore(): Observable<boolean> {
return this.store.select(fromRoot.getPlaylists)
.map(playlists => !!playlists)
.take(1);
}
getPlaylistsFromApi(): Observable<boolean> {
this.store.dispatch(new playlists.GetPlaylistsAction());
return this.store.select(fromRoot.getPlaylists)
.map(playlists => !!playlists)
.take(1);
}
hasPlaylists(): Observable<boolean> {
console.log('pew pew'); // nothing happens here =(
return this.hasPlaylistsInStore()
.switchMap(inStore => {
if (inStore) {
return of(inStore);
}
return this.getPlaylistsFromApi();
});
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
return this.waitForCollectionToLoad()
.switchMap(() => this.hasPlaylists());
}
}
loaded property exists in reducer and selected right. сode execution doesn't reach the hasPlaylists function so i think switchMap doesn't work, but i can't understand why =)
UPD: added router declaration
import {
PlaylistsExistsGuard
} from './guards';
{
path: 'playlists',
component: MusicComponent,
canActivate: [PlaylistsExistsGuard]
}
UPD: i think i found solution. if i using map instead filter here:
waitForCollectionToLoad(): Observable<boolean> {
return this.store.select(fromRoot.getPlaylistsLoaded)
.map(loaded => loaded) //here
.take(1);
}
and catching action here:
getPlaylistsFromApi(): Observable<boolean> {
this.store.dispatch(new playlists.GetPlaylistsAction());
return this.actions$
.ofType(playlists.GET_PLAYLISTS_COMPLETE)
.mapTo(true);
}
UPD: As @Skeptor advise in comments i don't need map
to take element so i can remove it here
waitForCollectionToLoad(): Observable<boolean> {
return this.store.select(fromRoot.getPlaylistsLoaded)
.take(1);
}
guard works fine, but i still don't understand why doesn't it works with filter =/