Angular 7结构指令仅在刷新浏览器后才有效

时间:2019-02-13 22:06:47

标签: angular jwt auth0

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

NavComponent.html:2错误TypeError:无法读取未定义的属性“角色”     在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 [作为updateDirectives](NavComponent.html:5)     在Object.debugUpdateDirectives [作为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>

3 个答案:

答案 0 :(得分:0)

我在我的一个项目中使用了类似的概念,以便根据当前用户的权限(=〜角色)显示或隐藏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方法返回一个可观察到的结果,因为在我的情况下,当指令请求结果时可能仍需要获取许可权(在这种情况下,这将是您的auth令牌,可能不是在SPA出生时可用。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

尝试在您的*ngIf=(loggedIn)标签中放置一个<ul>