Targaryen Targaryen - 2 months ago 6
TypeScript Question

Can't get app to navigate to portal

I'm trying to write a route guard. Here's my route...

{ path: 'portal', component: PortalComponent, canActivate: [AuthGuard] }


And here's AuthGuard:

@Injectable()
export class AuthGuard implements CanActivate {
constructor(private appState: ApplicationState, private router: Router) {}

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
let url: string = state.url;
return this.checkLogin(url);
}

checkLogin(url: string): Observable<boolean> {
return this.appState.User.map(
(user) => {
if (user.UserToken) return true;

this.navToLogin(url);
return false;
}
);
}

private navToLogin(redirUrl: string) {
this.appState.RedirectUrl = redirUrl;
this.router.navigate(['/']);
}
}


And here's ApplicationState where you get the User from...

@Injectable()
export class ApplicationState {
private _user: BehaviorSubject<LoginUser> = new BehaviorSubject<LoginUser>(new LoginUser());

get User() {
return this._user.asObservable();
}
}


I want the user to be able to access the /portal route if the UserToken exists on the User object. However, if the token does not exist, I want the user to navigate to the login page (default route /).

I have a link to /portal that I tried clicking. And the appState.User.map inside checkLogin() returns true, however, the app never navigates to /portal.

What am I doing wrong? Is this one of those "cold observable" situations?

Answer

Try this:

@Injectable()
export class ApplicationState {
    private _user: BehaviorSubject<LoginUser> = new BehaviorSubject<LoginUser>(new LoginUser());

    get User() {
        return this._user.value;
    }
    // login(user: LoginUser) { this._user.next(user); }
}


@Injectable()
export class AuthGuard implements CanActivate {
    // ...

    checkLogin(url: string): boolean {
      if (this.appState.User.UserToken) return true;

      this.navToLogin(url);
      return false;
    }

    // ...
}