Angular 4 - 如何将属性绑定到 * 指令

3
我已经在Angular 4中建立了一个“accessLevel”指令,它类似于*ngIf,但可以根据不同的权限级别进行控制。
@Directive({
  selector: '[accessLevel]'
})
export class AccessLevelDirective {
  private levelToPredicateMapper: {[id: string] : () => Observable<boolean>} = {};
  private isAuthorized: boolean;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private readonly credentialsStorage: CredentialsStorageService,
    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 isValidRolesArray = roles != null && Array.isArray(roles) && roles.length > 0;
        let isUserHasOneOfTheRoles = isAuthenticated && 
            isValidRolesArray && 
            this.credentialsStorage.get() &&
            some(this.credentialsStorage.get().roles , role => roles.indexOf(role) > -1);
        this.buildOrDestroyView(isUserHasOneOfTheRoles);
      })
  }

  private buildOrDestroyView(isAuthorized: boolean) {
    let isStateChanged = isAuthorized !== this.isAuthorized;
    if (!isStateChanged) return;
    this.isAuthorized = isAuthorized;

    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()
  }
}

我的问题是当我在HTML中使用时,为了绑定到角色属性,我需要用ng-template包装元素。

<!--Without [roles]-->
<a class="nav-item nav-link text-uppercase" *accessLevel="'authenticated'">
  ...         
</a>
<!--with [roles]-->
<ng-template accessLevel [roles]="['admin']">
  ...
</ng-template>

有没有一种方法可以绑定角色,而不需要将元素包装在ng-template标签中?
1个回答

1
当输入名称与选择器相同时
<input *accessLevel="['admin']" ...

应该可以工作

否则输入需要

@Input() set accessLevelRoles(roles: [string]) {

那么

<input *accessLevel="roles:['admin']" ...

应该可以工作。

1
似乎 *accessLevel="roles:['admin']" 是正确的。*accessLevel="something; roles:['admin']" - yurzui
没错,我之前也遇到过类似的问题。 - Günter Zöchbauer
*accessLevel="0, roles:['admin']" or *accessLevel="'authenticated', roles:['admin']" - yurzui

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接