如何绑定 PrimeNG MenuItem 的 'disabled' 属性?

How to bind 'disabled' property of PrimeNG MenuItem?

我正在使用 angular / primeng 开发应用程序并遇到了一个问题。

我正在使用 primeng TabMenu 组件,并希望根据用户是否登录来禁用某些选项卡,但我终究无法弄清楚如何绑定 'disabled' 属性 选项卡到变量。

这是我的代码:

component.html:

<p-tabMenu [model]="items">
</p-tabMenu>

component.ts:

export class TopMenuComponent implements OnInit {

    constructor(private auth: AuthService) { }

    items: MenuItem[];

    ngOnInit() {
        this.items = [
            {label: 'Home', routerLink: '/'},
            {label: 'Tab1',  routerLink: '/tab1'},
            {label: 'Tab2',  routerLink: '/tab2', disabled=!this.auth.isUserLoggedIn},
            {label: 'Tab3',  routerLink: '/tab3'},
        ];

    }
}

其中 auth.isUserLoggedIn 是一个根据用户登录或注销而变化的布尔值。

以上当然不起作用,因为 'disabled' 属性 仅在初始化期间设置为假值(正如预期的那样,因为用户尚未登录)。

我无法将 'disabled' 设置为函数或 Observable,因为 MenuItem 只接受布尔值。

我实际上通过创建一个可观察的 isUserLoggedInObservable 并以这种方式在 ngOnInit() 中订阅它来解决它:

this.auth.isUserLoggedInObservable.subscribe(value => {
          this.items[2].disabled = !value;
        })

但我觉得我一定是错过了解决问题的正确方法。

正确的做法是什么?

如果您不想在未登录时显示该选项卡,则应将 disabled 的值设置为 true。因此,代码将是:

this.items = [
  {label: 'Home', routerLink: '/'},
  {label: 'Tab1',  routerLink: '/tab1'},
  {label: 'Tab2',  routerLink: '/tab2', disabled= true},
  {label: 'Tab3',  routerLink: '/tab3'},
];

然后您将检查用户是否已登录。如果用户已登录,则将其设置为 false。因此,代码将是:

if (this.auth.isUserLoggedIn) {
  this.items[2].disabled = false
} else {
  this.items[2].disabled = true
}

这应该是您想要的正确方式。

编辑

如果你想让它可变,你应该使用 Subject;

auth.service.ts:

isLoggedIn = new Subject<boolean>;

islogged() { 
  if (islogged){ \condition for your loggedIn check
    this.isLoggedIn.next(true);
  } else {
    this.isLoggedIn.next(false);

component.ts

  ngOnInit() {
    this.items = [
      {label: 'Home', routerLink: '/'},
      {label: 'Tab1',  routerLink: '/tab1'},
      {label: 'Tab2',  routerLink: '/tab2', disabled= true},
      {label: 'Tab3',  routerLink: '/tab3'},
    ];
    this.auth.isLoggedIn.subscribe((res:boolean) => this.item[2].disabled = res);

您应该 avoid subscribing manually when possible,如果这样做,则需要清理您的订阅。解决这个问题的正确方法是让项目成为 Observable。然后,您使其取决于 auth 服务的 isUserLoggedInObservable 的结果,但以禁用状态启动流,如下所示:

export class TopMenuComponent implements OnInit {
    constructor(private auth: AuthService) {}

    items$: Observable<MenuItem[]>;

    ngOnInit() {
        this.items$ = this.auth.isUserLoggedInObservable.pipe(
          map(isLoggedIn => getMenuItems(isLoggedIn)),
          startWith(this.getMenuItems(false))
        );
    }

    private getMenuItems(isLoggedIn: boolean): MenuItem[] {
      return [
        { label: 'Home', routerLink: '/' },
        { label: 'Tab1',  routerLink: '/tab1' },
        { label: 'Tab2',  routerLink: '/tab2', disabled: !isLoggedIn },
        { label: 'Tab3',  routerLink: '/tab3' },
      ];
    }
}

然后您可以将模板中的 items$ 流与异步管道一起使用:

<p-tabMenu [model]="items$ | async"></p-tabMenu>

问题是如果其中一项 属性 更改,菜单项不会重新呈现。

您仍然可以使用 CSS 解决此问题:

  1. 在您的 html:
  2. 中创建一个异步条件 ngClass
<p-sidebar>
    <p-menu [model]="menuItems" [ngClass]="{'authenticated': (authState$ | async)}"></p-menu>
</p-sidebar>
  1. 将样式类“only-authenticated”添加到您要隐藏的菜单中:
  menuItems: MenuItem[] = [
    {
      label: 'help',
      icon: 'fal fa-question-circle',
      routerLink: '/help',
      styleClass: "only-authenticated"
    }
...
// import your Observable
  authState$ = this.authService.authState$;

  1. 最终将正确的样式添加到您的 css:
p-menu:not(.authenticated) {
  // user is not authenticated
  .only-authenticated {
    display: none;
  }
}