Adam S Adam S - 1 year ago 267
Node.js Question

Angular2 - Extending router and Observable

In angular2 rc2 with the router module v, I extend the RouterOulet to check if the user is logged in before accessing the admin. So this is the code :

selector: 'router-outlet'

export class LoggedInRouterOutlet extends RouterOutlet
publicRoutes: Array<string>;
private parentOutletMap: RouterOutletMap;
private userService: UserService;
private parentRouter: Router;

parentOutletMap: RouterOutletMap,
_location: ViewContainerRef,
@Attribute('name') name: string,
userService: UserService,
parentRouter: Router
) {
super(parentOutletMap, _location, name);

this.parentRouter = parentRouter;
this.parentOutletMap = parentOutletMap;
this.userService = userService;
this.publicRoutes = [

activate(factory: ComponentFactory<any>, activatedRoute: ActivatedRoute, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap)
if (this._canActivate(factory.selector)) {
return super.activate(factory, activatedRoute, providers, outletMap);


_canActivate(url) {
return this.publicRoutes.indexOf(url) !== -1 || this.userService.isLoggedIn()

userService.isLoggedIn() has to return a boolean. My question is : How do I adapt my code to make an http call to check if the user is logged in ? Because if the isLoggedIn method return an observable object, and I subscribe it, I can't return the result in the parent function.

Answer Source

Please notice that the result of activate method of OutletRouter has changed.


activate(nextInstruction: ComponentInstruction) : Promise<any>


activate(factory: ComponentFactory<any>, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) : ComponentRef<any>

which is not a Promise or Observable any more. New router implementation comes with a bit different solution that I think is cleaner: Guards.

A guard's return value controls the router's behavior:

if it returns true, the navigation process continues if it returns false, the navigation process stops and the user stays put The guard can also tell the router to navigate elsewhere, effectively canceling the current navigation.

The guard might return its boolean answer synchronously. But in many cases, the guard can't produce an answer synchronously. The guard could ask the user a question, save changes to the server, or fetch fresh data. These are all asynchronous operations.

Accordingly, a routing guard can return an Observable and the router will wait for the observable to resolve to true or `false.

You can create auth.guard.ts:

import { Injectable }             from '@angular/core';
import { CanActivate,
         RouterStateSnapshot }    from '@angular/router';
import { UserService }            from './user.service';

export class AuthGuard implements CanActivate {
  constructor(private userService: UserService, private router: Router) {}

    // Not using but worth knowing about
    next:  ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ) {
    return this.authService.isLoggedIn();

Now make sure your isLoggedIn return Promise (or Observable - try both as Angular2 Reference is not ready yet):

public isLoggedIn() : Promise<boolean> {
   return this.http.get('/api/check/logged')

Then just modify your RouterConfig array:

{ path: '/secret', component: SercetComponent, canActivate: [AuthGuard] }

Refer also to Angular2 Developer Guide