I'm developing an application using angular / primeng and came across an issue.
I'm using a primeng TabMenu component and would like some tabs to be disabled depending on whether a user is logged in or not, but I can't for the life of me figure out how to bind a 'disabled' property of a tab to a variable.
Here is my code:
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'},
];
}
}
where auth.isUserLoggedIn is a boolean changing value depending on user logging in or logging out.
The above of course doesn't work since the 'disabled' property is only set during init to a false value(as expected since user is not logged in yet).
I cannot set 'disabled' to a function or Observable since MenuItem only accepts boolean values.
I actually solved it by creating an observable isUserLoggedInObservable and subscribing to it in ngOnInit() this way:
this.auth.isUserLoggedInObservable.subscribe(value => {
this.items[2].disabled = !value;
})
but it feels to me that I must be missing the correct way of solving the issue.
How should it be done correctly?
You should avoid subscribing manually when possible, and if you do then you need to cleanup your subscription. The proper way to solve this is to have the items be an Observable. You then make it depend on the outcome of the isUserLoggedInObservable of the auth service, but kick off the stream with the disabled state like so:
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' },
];
}
}
You can then use the items$ stream in the template with the async pipe:
<p-tabMenu [model]="items$ | async"></p-tabMenu>