Introducing CrudHunt:Open-source Full-stack CRUDs for Next.js by KeenThemes
Browse CrudHunt

After clicking one parent menu with sub , all other parent menus are expanding with duplicates of existing menu


<!--begin::Menu wrapper-->
<div
id="kt_app_sidebar_menu_wrapper"
class="app-sidebar-wrapper hover-scroll-overlay-y my-5"
data-kt-scroll="true"
data-kt-scroll-activate="true"
data-kt-scroll-height="auto"
data-kt-scroll-dependencies="#kt_app_sidebar_logo, #kt_app_sidebar_footer"
data-kt-scroll-wrappers="#kt_app_sidebar_menu"
data-kt-scroll-offset="5px"
data-kt-scroll-save-state="true"
>
<!--begin::Menu-->
<div
class="menu menu-column menu-rounded menu-sub-indention px-3"
id="#kt_app_sidebar_menu"
data-kt-menu="true"
data-kt-menu-expand="false"
>
<!-- Pages -->
<ng-container *ngIf="isAdmin">
<ng-container *ngFor="let item of ParentMenuList">
<div
class="menu-item"
*ngIf="
willSeparatorPrint(item.SEPARATOR_GROUP_ID, item.MENU_ITEM_ID) == 'Y'
"
>
<div class="menu-content pt-8 pb-2">
<span class="menu-section text-muted text-uppercase fs-8 ls-1">{{
separatorLabel
}}</span>
</div>
</div>
<div
class="menu-item menu-accordion"
data-kt-menu-trigger="click"
(click)="getChild1Menu(item.MENU_ITEM_ID)" routerLinkActive="here show"
>
<span class="menu-link">
<span class="menu-icon">
<span class="svg-icon svg-icon-2" [inlineSVG]="item.ICON_SVG"></span
></span>
<span class="menu-title" >{{ item.MENU_DESCRIPTION }}</span>
<span class="menu-arrow"></span
></span>
<ng-container *ngFor="let child1 of child1List">
<div
class="menu-sub menu-sub-accordion"
(click)="getChild2Menu(child1.MENU_ITEM_ID)"
>
<div class="menu-item menu-accordion" data-kt-menu-trigger="click" routerLinkActive="here show">
<span class="menu-link"
><span class="menu-bullet"
><span class="bullet bullet-dot"></span></span
><span class="menu-title" data-link="child1.MENU_URL">{{
child1.MENU_DESCRIPTION
}}</span
><span class="menu-arrow"></span
></span>

<ng-container *ngFor="let child2 of child2List">
<div
class="menu-sub menu-sub-accordion"
routerLinkActive="menu-active-bg"
>
<div class="menu-item">
<a
class="menu-link without-sub"
routerLinkActive="active"
[routerLink]="child2.MENU_URL"
><span class="menu-bullet"
><span class="bullet bullet-dot"></span></span
><span class="menu-title">{{
child2.MENU_DESCRIPTION
}}</span></a
>
</div>
</div>
</ng-container>
</div>
</div>
</ng-container>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="isStudent">
<div class="menu-item">
<div class="menu-content pt-8 pb-2">
<span class="menu-section text-muted text-uppercase fs-8 ls-1">{{separatorName}}</span>
</div>
</div>
<ng-container *ngFor="let item of MenuListTeacherStudnet">
<div class="menu-item">
<a class="menu-link without-sub" [routerLink]="item.MENU_URL" routerLinkActive="active"><span class="menu-bullet"><span
class="bullet bullet-dot"></span></span>
<span class="menu-title">{{item.MENU_DESCRIPTION}}</span></a>
</div>
</ng-container>
</ng-container>

</div>
<!--end::Menu-->
</div>
<!--end::Menu wrapper-->
when routerLinkActive="here show" is applied in child1 menu then it duplicates the current parent child menus under other parent menus, all of them get expanded


Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(

Replies (2)


Hi,

You can try the following possible solutions:

Remove routerLinkActive from Parent Menus:
Remove the routerLinkActive directive from the parent menus in your template. This directive is intended for identifying the active route, and applying it to parent menus might cause unexpected behavior.

<div
class="menu-item menu-accordion"
data-kt-menu-trigger="click"
(click)="getChild1Menu(item.MENU_ITEM_ID)"
>
<!-- ... your menu content ... -->
</div>


Update Child Menus to Use RouterLinkActive:
Apply the routerLinkActive directive only to the child menus where you want to indicate the active route.

<div class="menu-sub menu-sub-accordion" routerLinkActive="here show">
<div class="menu-item menu-accordion" data-kt-menu-trigger="click" (click)="getChild2Menu(child1.MENU_ITEM_ID)">
<!-- ... your child menu content ... -->
</div>
</div>

Ensure Correct Routes:
Make sure that your routes are correctly defined and match the structure you are using in your routerLink directives.
Use Angular's RouterLink Directive:
Instead of directly using the routerLink attribute, consider using Angular's routerLink directive with an array for better readability and flexibility.

<a class="menu-link without-sub" [routerLink]="[child2.MENU_URL]" routerLinkActive="active">
<!-- ... your menu content ... -->
</a>


This can help in handling complex route structures.

Run Change Detection After Menu Changes:
After updating menu lists (child1List, child2List), you might need to run change detection explicitly using Angular's ChangeDetectorRef to ensure that the changes are reflected in the view.

import { ChangeDetectorRef } from "@angular/core";

// ...

constructor(private cdr: ChangeDetectorRef, private menuService: MenuService) {
// ...
}

// ...

getChild1Menu(MenuItemId: number) {
this.child1List = this.DBmenuList.filter(w => w.PARENT_MENU_ITEM_ID == MenuItemId);
this.cdr.detectChanges(); // Run change detection
}

getChild2Menu(MenuItemId: number) {
this.child2List = this.DBmenuList.filter(w => w.PARENT_MENU_ITEM_ID == MenuItemId);
this.cdr.detectChanges(); // Run change detection
}


Apply these changes and check if the issue persists. If the problem continues, you may need to investigate further, checking the console for any error messages or unexpected behaviors.



import { M } from '@angular/cdk/keycodes';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ResponseMessage } from 'src/app/models/response-message';
import { MenuService } from 'src/app/services/menu.service';

@Component({
selector: 'app-sidebar-menu',
templateUrl: './sidebar-menu.component.html',
styleUrls: ['./sidebar-menu.component.scss'],
})
export class SidebarMenuComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
userCode: any = localStorage.getItem('userCode');
roleId: any = localStorage.getItem('roleId');
userType = localStorage.getItem('userType');
DBmenuList: any;
menuList: any[];
MenuListTeacherStudnet: any[];
ParentMenuList: any;
child1List: any;
child2List: any;
separatorName: string;
separatorLabel: string;

isAdmin: boolean = true;
isStudent: boolean = false;

constructor(
private cdr: ChangeDetectorRef,
private menuService: MenuService
) {
this.menuShow();
this.getDBmenuList();
this.getDBmenuListForTeacherStudent();
}

ngOnInit(): void {}

menuShow(){
if (this.userType == 'Student') {

this.separatorName = 'STUDENT';
this.isAdmin = false;
this.isStudent = true;
} else if (this.userType == 'Teacher') {
this.separatorName = 'TEACHER';
this.isAdmin = false;
this.isStudent = true;
}
}

getDBmenuListForTeacherStudent() {
this.DBmenuList = this.menuService.GetDBMenuList();
this.MenuListTeacherStudnet = this.DBmenuList.filter(
(w) => w.MENU_ITEM_ID != 0 && w.PARENT_MENU_ITEM_ID != 0
&& w.MENU_URL != null
);
}

getDBmenuList() {
this.DBmenuList = this.menuService.GetDBMenuList();
this.ParentMenuList = this.DBmenuList.filter(
(w) => w.PARENT_MENU_ITEM_ID == 0 && w.IS_MENU === 'Y'
);
}

getChild1Menu(MenuItemId: number) {
this.child1List = this.DBmenuList.filter(
(w) => w.PARENT_MENU_ITEM_ID == MenuItemId
);
}

getChild2Menu(MenuItemId: number) {
this.child2List = this.DBmenuList.filter(
(w) => w.PARENT_MENU_ITEM_ID == MenuItemId
);
}

willSeparatorPrint(separatorGroupId: number, menuItemId: number) {
let itemCount: number = this.DBmenuList.filter(
(w) => w.SEPARATOR_GROUP_ID == separatorGroupId && w.IS_MENU == 'N'
).length;

if (itemCount > 0) {
let firstMenuItemId: number = this.DBmenuList.filter(
(w) => w.SEPARATOR_GROUP_ID === separatorGroupId
)[0].MENU_ITEM_ID;
if (firstMenuItemId == menuItemId) {
this.separatorLabel = this.DBmenuList.filter(
(w) => w.SEPARATOR_GROUP_ID === separatorGroupId && w.IS_MENU == 'N'
)[0].MENU_DESCRIPTION;
return 'Y';
} else {
return 'N';
}
} else {
return 'N';
}
}


ngOnDestroy() {
this.subscriptions.forEach((sb) => sb.unsubscribe());
}
}
here is my ts file


Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(
Text formatting options
Submit
Here's a how to add some HTML formatting to your comment:
  • <pre></pre> for JS codes block
  • <pre lang="html"></pre> for HTML code block
  • <pre lang="scss"></pre> for SCSS code block
  • <pre lang="php"></pre> for PHP code block
  • <code></code> for single line of code
  • <strong></strong> to make things bold
  • <em></em> to emphasize
  • <ul><li></li></ul>  to make list
  • <ol><li></li></ol>  to make ordered list
  • <h3></h3> to make headings
  • <a></a> for links
  • <img> to paste in an image
  • <blockquote></blockquote> to quote somebody
  • happy  :)
  • shocked  :|
  • sad  :(