I have an application that works based on user access. I check which environment the user is in and which features they have access to within that environment, and after that, I list the features as navigation items in my menu.
Initially, my menu will have two items, a navigation link to the “home” screen and a button that logs the user out of the application. The other items (navigation links) are loaded dynamically. These items can be “basic” or “collapsable”.
When the application starts, the user is redirected to the Home screen, and their access list is loaded. However, when I select an item to navigate, all of my items are being selected (they are all receiving the “menu-item-active” class) and their “href” values are being changed to the link of the selected item. Why is this happening, and how can I fix it? Please help!!! ;(
menu.component.html:
<ion-menu type="overlay" [contentId]="contentId">
<ion-header>
<ion-toolbar>
<ion-menu-button slot="start">
<ion-icon name="close-outline"></ion-icon>
</ion-menu-button>
<ion-title>MENU</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list class="ion-padding">
<a routerLink="home"
[routerLinkActive]="'menu-item-active'"
[routerLinkActiveOptions]="{ exact: true }"
class="menu-item"
(click)="closeMenu()">
<mat-icon>home</mat-icon>
<ion-label>Home</ion-label>
</a>
<ng-container *ngFor="let item of navigationItems">
<ng-container *ngIf="item.type === 'basic'">
<a [routerLink]="item.link"
[routerLinkActive]="'menu-item-active'"
[routerLinkActiveOptions]="{ exact: true }"
class="menu-item"
(click)="closeMenu()">
<mat-icon>{{ item.icon }}</mat-icon>
<ion-label>{{ item.title }}</ion-label>
</a>
</ng-container>
<ng-container *ngIf="item.type === 'collapsable'">
<ion-accordion-group>
<ion-accordion>
<ion-item slot="header" class="menu-item-header">
<mat-icon class="menu-item-header-icon">{{ item.icon }}</mat-icon>
<ion-label>{{ item.title }}</ion-label>
</ion-item>
<div slot="content">
<ion-list *ngIf="item.children && item.children.length > 0">
<a *ngFor="let child of item.children"
[routerLink]="child.link"
[routerLinkActive]="'menu-item-active'"
[routerLinkActiveOptions]="{ exact: true }"
class="menu-item"
(click)="closeMenu()">
<mat-icon>{{ child.icon }}</mat-icon>
<ion-label>{{ child.title }}</ion-label>
</a>
</ion-list>
</div>
</ion-accordion>
</ion-accordion-group>
</ng-container>
</ng-container>
<ion-button class="logout-button" fill="clear" (click)="onLogout()">
<span class="logout-button-content">
<ion-icon name="log-out-outline"></ion-icon>
<ion-label>Sair</ion-label>
</span>
</ion-button>
</ion-list>
</ion-content>
<ion-footer>
<ion-item>footer</ion-item>
</ion-footer>
</ion-menu>
menu.component.ts:
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { AuthService } from 'src/app/core/auth/auth.service';
import { MenuNavigationItem } from './menu.model';
import { UserAccessService } from 'src/app/core/user-access/user-access.service';
import { Functionality } from 'src/app/core/auth/auth.model';
import { MenuController } from '@ionic/angular';
@Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.scss'],
})
export class MenuComponent implements OnInit, OnDestroy {
private _unsubscribeAll: Subject<any> = new Subject<any>();
@Input() contentId: string;
public navigationItems: MenuNavigationItem[] = [];
constructor(
private _authService: AuthService,
private _userAccessService: UserAccessService,
private _menuController: MenuController
) { }
private verifyUserAccessInEnvironment(funccionalities: Functionality[]): boolean {
return funccionalities.length === 0 ? false : true;
}
private fillNavigationItems(): void {
let filteredFuncionalities: Functionality[] = [];
this._userAccessService.getFilteredFuncionalitiesIds()
.then((functionalities: Functionality[]) => {
filteredFuncionalities = functionalities;
this.navigationItems = this._userAccessService.getPowerBiFunctionalitiesNavigation(filteredFuncionalities);
this._userAccessService.hasPowerBiAccessInCurrentEnvironment
.next(this.verifyUserAccessInEnvironment(functionalities));
});
}
ngOnInit(): void {
this._userAccessService.currentEnvironmentId
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
this.fillNavigationItems();
});
}
closeMenu(): void {
this._menuController.close();
}
onLogout(): void {
this._authService.logout();
}
ngOnDestroy(): void {
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}
Here is an example of items loaded for navigation:
[
{
"id": "703",
"title": "ITEM 1",
"type": "collapsable",
"icon": "business",
"children": [
{
"id": "778",
"title": "ITEM 1.1",
"type": "basic",
"icon": "",
"link": "item/778",
"children": []
},
{
"id": "838",
"title": "ITEM 1.2",
"type": "basic",
"icon": "",
"link": "item/838",
"children": []
},
{
"id": "751",
"title": "ITEM 1.3",
"type": "basic",
"icon": "",
"link": "item/751",
"children": []
}
]
},
{
"id": "701",
"title": "ITEM 2",
"type": "collapsable",
"icon": "pets",
"children": [
{
"id": "813",
"title": "ITEM 2.1",
"type": "basic",
"icon": "",
"link": "item/813",
"children": []
},
{
"id": "810",
"title": "ITEM 2.2",
"type": "basic",
"icon": "",
"link": "item/810",
"children": []
}
]
}
]
OBS: Since the “closeMenu()” method is called whenever an item is selected, I called the “fillNavigationItems()” method inside it and added a “console.log(this.navigationItems);” The items are all correct, with their respective links. However, for some reason, when I check each item in the browser’s developer tools, all items have the “menu-item-active” class and the “href” with the value of the last selected item.