2017-07-30 9 views
1

ユーザーの権限に従ってビューの一部を表示するには、角度4のディレクティブを作成しました。 このディレクティブは、アプリケーションの読み込み時に起動されますが、ログインまたはログアウト後に呼び出されることはありません。本当に助けになるだろう。角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を記述する方が良いだろう。

しかし、一般的に:

あなたのディレクティブは(ログインまたはしない)状態を認識していない限り、それはつもりではないのですが、外の世界に反応します。

多くのそれを動作させるための方法のがあります。@Inputsを通して

の1-:

あなたは@Input set stateを持つことができますし、状態はログインかないと、あなたが反応することができることに基づくことができる(ランどんな機能ルータの状態を使用して

2- like`:

あなたのディレクティブにRouterを注入し、それを購読することができ、変更することだとルートが変更にあるとき/loginその後、共有、観察経由で機能(お使いの再評価)

、3-を実行することができます:あなたはSubjectを作成し、コンポーネントとあなたのディレクティブの間でそれを共有し、ディレクティブが購読しましょう可能性が

をとし、コンポーネントはイベントを発生させ、それに基づいて再評価を実行します。

+0

Miladはあなたの助けに感謝します。私はあなたが推奨するようにユーザーの主題に決定し、それは素晴らしい動作するようです。 Observable.ofのように、predfined値を持つSubject.asObservableを返す方法はありますか?もしそうなら、Subject.asObservable()をauthentication.isAuthenticatedから返すことができます。 –

+0

あなたはそれを行うことはできませんが、代わりにBehaviorSubjectを使用して初期値を受け入れることができます – Milad

関連する問題