2017-07-30 79 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