最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular2 - Extending router and Observable - Stack Overflow

programmeradmin8浏览0评论

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

@Directive({
    selector: 'router-outlet'
})

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

    constructor(
        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 = [
            'public', 
            'login'
        ];
    }

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

        this.parentRouter.navigate(['/login']);
    }

    _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.

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

@Directive({
    selector: 'router-outlet'
})

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

    constructor(
        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 = [
            'public', 
            'login'
        ];
    }

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

        this.parentRouter.navigate(['/login']);
    }

    _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.

Share Improve this question asked Jun 17, 2016 at 19:14 Adam SAdam S 1,0312 gold badges14 silver badges25 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

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

@angular/router-deprecated

activate(nextInstruction: ComponentInstruction) : Promise<any>

@angular/router

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

which is not a Promise or Observable any more. New router implementation es 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,
         Router,
         ActivatedRouteSnapshot,
         RouterStateSnapshot }    from '@angular/router';
import { UserService }            from './user.service';

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

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

Now make sure your isLoggedIn return Observable (or Promise - try both as Angular2 Reference is not ready yet). In my case API returns JSON in format: { success: true / false }.

public isLoggedIn() : Observable<boolean> | boolean {
    let router: Router = this.router;
    let obs;

    try {
        obs = this.authHttp.get('/api/check/logged')
            .map(result => result.json())
            .map(resultJson => (resultJson && resultJson.success));

    } catch (err) {
        obs = Observable.of(false);
    }

    return obs
        .map(success => {
             // navigate to login page
             if (!success)
                 router.navigate(['/auth/login']);

             return success;
        });
}

Then just modify your RouterConfig array:

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

Refer also to Angular2 Developer Guide

发布评论

评论列表(0)

  1. 暂无评论