Angular 4指令不是重新评估

时间:2017-07-30 10:53:20

标签: angular angular2-directives

我创建了一个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()
  }
}
&#13;
<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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

我无法看到你的指令应该如何&#34;重新评估&#34;在您登录后 首先,最好描述re-evaluation

但一般情况下:

除非你的指令知道状态(登录或不登录),否则它不会对外界做出反应。

有很多方法可以让它发挥作用:

1-通过@Inputs

你可以拥有一个@Input set state,状态是否可以登录,并根据你可以做出的反应(运行你喜欢的任何功能)

2-使用路由器状态:

您可以将Router注入您的指令并订阅它的更改,当路线更改为/login时,您可以运行您的功能(您的重新评估)

3-通过共享的observable:

你可以创建一个Subject并在你的组件和你的指令之间共享它,并让指令订阅,并且组件将触发一个事件,并根据该运行你的重新评估。