Reputation: 33
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?
Upvotes: 3
Views: 7699
Reputation: 117
The issue is that the menu item does not redender if one of its property change.
You still could solve this using CSS:
<p-sidebar>
<p-menu [model]="menuItems" [ngClass]="{'authenticated': (authState$ | async)}"></p-menu>
</p-sidebar>
menuItems: MenuItem[] = [
{
label: 'help',
icon: 'fal fa-question-circle',
routerLink: '/help',
styleClass: "only-authenticated"
}
...
// import your Observable
authState$ = this.authService.authState$;
p-menu:not(.authenticated) {
// user is not authenticated
.only-authenticated {
display: none;
}
}
Upvotes: 1
Reputation: 5530
you should set the value of disabled to true if you don't want to show the tab if you are not logged in. So, the code will be:
this.items = [
{label: 'Home', routerLink: '/'},
{label: 'Tab1', routerLink: '/tab1'},
{label: 'Tab2', routerLink: '/tab2', disabled= true},
{label: 'Tab3', routerLink: '/tab3'},
];
Then you will check if the user is loggedIn. If the user is logged in, you turn it to false. So, the code will be:
if (this.auth.isUserLoggedIn) {
this.items[2].disabled = false
} else {
this.items[2].disabled = true
}
This should be the right way what you wanted.
Edit
If you want to make it changeable, you should use 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);
Upvotes: 1
Reputation: 302
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>
Upvotes: 4