2016-06-17 103 views
3

在包含路由器模塊v 3.0.0.6alpha的angular2 rc2中,我擴展了RouterOulet以在訪問管理員之前檢查用戶是否已登錄。所以這是代碼:Angular2 - 擴展路由器和Observable

@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()必須返回一個布爾值。我的問題是:如何調整我的代碼以進行http調用以檢查用戶是否已登錄?因爲如果isLoggedIn方法返回一個可觀察對象,並且我訂閱了它,我不能在父函數中返回結果。

回答

8

請注意,OutletRouter的激活方法的結果已更改。

@角/路由器棄用

activate(nextInstruction: ComponentInstruction) : Promise<any>

@角/路由器

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

其不是無極或可觀察的任何更多。新的路由器實現有一個不同的解決方案,我認爲它更清潔:防護。

一個後衛的返回值控制路由器的行爲:

如果返回true,導航過程繼續,如果返回 假,導航過程停止,用戶原地踏步的後衛 也可以告訴路由器導航到其他地方,有效取消當前導航 。

警衛可能會同步返回它的布爾答案。但在許多情況下,警衛無法同步產生答案。警衛 可能會詢問用戶一個問題,保存對服務器的更改或獲取新數據。這些都是異步操作。

因此,路由警衛可以返回Observable,並且路由器將等待observable解析爲true或false。

您可以創建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(); 
    } 
} 

現在確保您的isLoggedIn返回觀察,(或無極 - 嘗試既作爲Angular2參考是not ready yet)。在我的情況下,API以格式返回JSON:{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; 
     }); 
} 

然後,只需修改RouterConfig陣列:

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

也可以參考Angular2 Developer Guide

+0

似乎不錯,謝謝!但我不知道在哪裏注射這名後衛?如果你可以編輯你的代碼來顯示它... –

+0

發佈原始答案後,我做了幾分鐘;)我忘了添加此之前。 – Baumi

+0

整潔!再次感謝 –