1

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 =/

amberhiri
  • 11
  • 3
  • Can you edit the question, and add the route declaration where you are trying to use the guard? – R. Richards Jul 03 '17 at 21:54
  • @R.Richards done. i'm pretty sure my router declaration is right. guard works fine if i switch filter operator in waitForCollectionToLoad function to map but with map route activates before playlists loaded from api. – amberhiri Jul 03 '17 at 22:00
  • are you dispatching correctly? is the reducer triggered? – Aravind Jul 03 '17 at 23:31
  • map(loaded=>loaded) is as good as not putting that statement – Vamshi Jul 04 '17 at 03:43
  • @Aravind reducer is not triggered. as i said, code execution with `filter` doesn't reach dispatching – amberhiri Jul 04 '17 at 06:44
  • @Skeptor can you explain, pls? – amberhiri Jul 04 '17 at 07:12
  • `map` takes an element converts it and passes it in place of original element. Here you are saying, take the element and replace with same element, which effectively means nothing – Vamshi Jul 04 '17 at 07:49
  • Oh, thanks so much. It means i can just `return this.store.select(fromRoot.getPlaylistsLoaded).take(1);` – amberhiri Jul 04 '17 at 08:34

0 Answers0