2017-07-30 101 views
1

我創建了一個角度4指令,以便根據用戶的權限顯示部分視圖。 加載應用程序時會觸發指令,但在登錄或註銷後不會調用它們,導致視圖保持不變,但用戶權限已更改。會真的提供一些幫助。Angular 4指令不是重新評估

@Directive({ 
 
    selector: '[accessLevel]' 
 
}) 
 
export class AccessLevelDirective { 
 
    private levelToPredicateMapper: {[id: string] :() => Observable<boolean>} = {}; 
 

 
    constructor(
 
    private templateRef: TemplateRef<any>, 
 
    private viewContainer: ViewContainerRef, 
 
    private readonly credantialsStorage: CredantialsStorageService, 
 
    private readonly authentication: AuthenticationService) { 
 

 
    this.createAccessLevelToPredicatesMapper(); 
 
    } 
 
    
 
    @Input() set accessLevel(level: string) { 
 
    if (level == null) { 
 
     return; 
 
    } 
 

 
    let hasAccessLevelFunc = this.levelToPredicateMapper[level]; 
 
    if (hasAccessLevelFunc == null) { 
 
     this.viewContainer.clear(); 
 
     return; 
 
    } 
 

 
    hasAccessLevelFunc().subscribe(hasAccessLevel => { 
 
     this.buildOrDestroyView(hasAccessLevel); 
 
    }) 
 
    } 
 

 
    @Input() set roles(roles: [string]) { 
 
    this.authentication.isAuthenticated() 
 
     .subscribe(isAuthenticated => { 
 

 
     let isValidArrayWithRoles = roles != null && Array.isArray(roles) && roles.length > 0; 
 
     let isUserHasOneOfTheRoles = isAuthenticated && 
 
      this.credantialsStorage.get() && 
 
      isValidArrayWithRoles && 
 
      some(this.credantialsStorage.get().roles , role => roles.indexOf(role) > -1); 
 
     this.buildOrDestroyView(isUserHasOneOfTheRoles); 
 
     }) 
 
    } 
 

 
    private buildOrDestroyView(isAuthorized: boolean) { 
 
    if (isAuthorized) { 
 
     this.viewContainer.createEmbeddedView(this.templateRef); 
 
    } else { 
 
     this.viewContainer.clear(); 
 
    } 
 
    } 
 

 
    private createAccessLevelToPredicatesMapper() { 
 
    this.levelToPredicateMapper['all'] =() => Observable.of(true); 
 
    this.levelToPredicateMapper['guest'] =() => this.authentication.isAuthenticated().map(isAuth => !isAuth); 
 
    this.levelToPredicateMapper['authenticated'] =() => this.authentication.isAuthenticated() 
 
    } 
 
}
<div id="navbar-menu" class="collapse navbar-collapse float-xs-none" [ngbCollapse]="menuHidden"> 
 
     <div class="navbar-nav"> 
 
     <a class="nav-item nav-link text-uppercase" routerLink="/login" routerLinkActive="active" *accessLevel="'guest'"> 
 
      <i class="fa fa-home"></i> 
 
      <span translate>Login</span> 
 
     </a> 
 
     <a class="nav-item nav-link text-uppercase" routerLink="/registration" routerLinkActive="active" *accessLevel="'guest'"> 
 
      <i class="fa fa-home"></i> 
 
      <span translate>Register</span> 
 
     </a> 
 
     <a class="nav-item nav-link text-uppercase" routerLink="/home" routerLinkActive="active"> 
 
      <i class="fa fa-home"></i> 
 
      <span translate>Home</span> 
 
     </a> 
 
     <a class="nav-item nav-link text-uppercase" routerLink="/about" routerLinkActive="active"> 
 
      <i class="fa fa-question-circle"></i> 
 
      <span translate>About</span> 
 
     </a> 
 
     <a class="nav-item nav-link text-uppercase" routerLink="/order/new" routerLinkActive="active"> 
 
      <i class="fa fa-question-circle"></i> 
 
      <span translate>Create Order</span> 
 
     </a> 
 
     <a class="nav-item nav-link text-uppercase" routerLink="/orders" routerLinkActive="active" *accessLevel="'authenticated'"> 
 
      <i class="fa fa-question-circle"></i> 
 
      <span translate>My Orders</span> 
 
     </a> 
 
     <ng-template accessLevel [roles]="['admin']"> 
 
      <a class="nav-item nav-link text-uppercase" routerLink="/admin" routerLinkActive="active"> 
 
       <i class="fa fa-question-circle"></i> 
 
       <span translate>Admin</span> 
 
      </a> 
 
     </ng-template> 
 
     </div>

回答

1

我看不出你的指令應該「重新評估」你登錄後 首先,這將是更好的描述re-evaluation

但一般:

除非你的指令是知道的狀態(登錄或沒有),這是不是要去給外界的反應。

有很多方法很多的,使其工作:

1-通過@Inputs

你可以有一個@Input set state和國家可以先登錄與否,並根據你反應過來(運行你like`任何功能

2-使用路由器狀態:

你可以注入Router你的指令,並訂閱它的變化和在路由改變/login那麼你可以通過一個共享觀測的運行功能(你重新評估)

3-:

您可以創建一個Subject和您的組件和您的指令之間共享,讓指令訂閱並和組件會觸發一個事件並基於該事件運行您的重新評估。

+0

Milad謝謝你的幫助。我決定按照你的建議使用用戶主題,它似乎很好。 有沒有一種方法來返回Subject.asObservable與預定義值(如Observable.of)?如果是這樣,我可以從authentication.isAuthenticated返回Subject.asObservable()。 –

+0

你不能那樣做,但你可以使用BehaviorSubject接受一個初始值 – Milad