【问题标题】:Angular 7 structural directive only works after refreshing the browserAngular 7 结构指令仅在刷新浏览器后才有效
【发布时间】:2019-07-07 21:03:33
【问题描述】:

我正在使用角度 7 到 7 的结构指令来根据用户角色隐藏应用程序的某些部分。用户角色从 jwt 令牌中解码。但是我遇到了问题。我在 Angular 6 中使用了相同的实现并且没有任何问题,但是我尝试的任何方法似乎都不起作用。如果我以管理员身份登录,我需要刷新浏览器以显示或隐藏管理员链接(如果我以普通用户身份登录)。错误消息已在下面发布,我添加了 hasRole.directive 和 html 链接

NavComponent.html:2 错误类型错误:无法读取未定义的属性“角色” 在 HasRoleDirective.push../src/app/_directives/hasRole.directive.ts.HasRoleDirective.ngOnInit (hasRole.directive.ts:17) 在 checkAndUpdateDirectiveInline (core.js:20665) 在 checkAndUpdateNodeInline (core.js:21929) 在 checkAndUpdateNode (core.js:21891) 在 debugCheckAndUpdateNode (core.js:22525) 在 debugCheckDirectivesFn (core.js:22485) 在 Object.eval [as updateDirectives] (NavComponent.html:5) 在 Object.debugUpdateDirectives [as updateDirectives] (core.js:22477) 在 checkAndUpdateView (core.js:21873) 在 callViewAction (core.js:22114)

import { Directive, Input, ViewContainerRef, TemplateRef, OnInit } from '@angular/core';
import { AuthService } from '../_services/auth.service';

@Directive({
  selector: '[appHasRole]'
})
export class HasRoleDirective implements OnInit {
  @Input() appHasRole: string[];
  isVisible = false;

  constructor(
    private viewContainerRef: ViewContainerRef,
    private templateRef: TemplateRef<any>,
    private authService: AuthService) { }

  ngOnInit() {
    const userRoles = this.authService.decodedToken.role as Array<string>;
    // if no roles clear the view container ref
    if (!userRoles) {
      this.viewContainerRef.clear();
    }

    // if user has role needed then render the element
    if (this.authService.roleMatch(this.appHasRole)) {
      if (!this.isVisible) {
        this.isVisible = true;
        this.viewContainerRef.createEmbeddedView(this.templateRef);
      } else {
        this.isVisible = false;
        this.viewContainerRef.clear();
      }
    }
  }

}
<ul class="navbar-nav">
        <li *appHasRole="['Admin', 'Moderator']"  class="nav-item" routerLinkActive="active" >
            <a class="nav-link" [routerLink]="['/admin']"  id="side-menu">Admin</a>
          </li>

【问题讨论】:

    标签: angular jwt auth0


    【解决方案1】:

    我在我的一个项目中使用了类似的概念,以便根据当前用户的权限 (=~role) 显示或隐藏 DOM 元素。

    建议:您的authService.decodedToken 属性似乎在某些时候未定义-您可以在authService 中使用RxJS 主题/可观察组合来将当前用户的角色传播给订阅者。然后在您的指令中订阅该属性,以显示或隐藏元素。我的实现看起来有点像这样(实际的显示/隐藏可能会有所不同,但你仍然应该明白我的意思):

      ngOnInit() {
        this.shouldDisplay().subscribe((shouldDisplay) => {
          if (shouldDisplay && !this.hasView) {
            this.show();
          } else if (!shouldDisplay && this.hasView) {
            this.hide();
          }
        });
      }
    
      [...]
    
      shouldDisplay(): Observable<boolean> {
        return this.permissionService.isPermitted(this.permission);
      }
    

    isPermitted 方法返回结果的 observable,因为在我的情况下,当指令请求结果时可能仍需要获取权限(在这种情况下,这将是您的身份验证令牌,可能无法在SPA诞生)。

    【讨论】:

      【解决方案2】:

      这个指令很好。我在 Angular 6、7 和 8 中使用了相同的指令,没有任何问题。

      1. 确保将您的常规用户角色传递到指令中
      2. 您是否尝试将指令移动到 viewContainerRef 中的锚标记?
          <a *appHasRole="['Admin', 'Moderator']" class="nav-link" [routerLink]="['/admin']"  id="side-menu">Admin</a>
      

      【讨论】:

        【解决方案3】:

        我不知道您是否解决了这个问题,但我认为您正在尝试在登录之前显示管理员链接。 如果您没有登录,您将没有要解码的令牌,并且您会收到未定义的错误。

        尝试在您的&lt;ul&gt; 标记中添加*ngIf=(loggedIn)

        【讨论】:

        • 在你的 ul 标签中*
        猜你喜欢
        • 1970-01-01
        • 2022-07-30
        • 2014-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-24
        • 2017-03-30
        • 2017-05-13
        相关资源
        最近更新 更多