Get 2024 Templates Mega Bundle!19 Bootstrap HTML, Vue & React Templates + 3 Vector Sets
Get for 99$

Metronic Angular Menu Minimized on Refresh


Hi,
Metronic angular menu is minimized on refresh.
Please give a solution.


Html code:

<!--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 -->
<div class="menu-item">
<a class="menu-link without-sub" routerLink="/dashboard" routerLinkActive="active"><span class="menu-icon">
<span [inlineSVG]="'./assets/media/icons/duotune/general/gen025.svg'" class="svg-icon svg-icon-2"></span>
</span>
<span class="menu-title" translate="MENU.DASHBOARD"></span></a>
</div>
<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"
>
<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">
<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>
</div>
<!--end::Menu-->
</div>
<!--end::Menu wrapper-->


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 (9)


Hi,

It seems like you're facing an issue with maintaining the expanded state of your menu when the page is refreshed. One way to address this is to determine the active menu item based on the current URL. You can achieve this by comparing the current URL with the URLs of the menu items.

Here's an example of how you can modify your SidebarMenuComponent to detect the active menu item using the current URL:

Update SidebarMenuComponent:


// sidebar-menu.component.ts
import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from "@angular/core";
import { DOCUMENT } from "@angular/common";
import { Router, NavigationEnd } from "@angular/router"; // Import Router and NavigationEnd
import { Subscription } from "rxjs";
import { filter } from "rxjs/operators"; // Import filter operator
import { MenuService } from "src/app/services/menu.service";

interface DataItem {
MENU_ITEM_ID: number;
PARENT_MENU_ITEM_ID: number;
MENU_DESCRIPTION: string;
MENU_URL: string;
}

@Component({
selector: "app-sidebar-menu",
templateUrl: "./sidebar-menu.component.html",
styleUrls: ["./sidebar-menu.component.scss"],
})
export class SidebarMenuComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
ParentMenuList: any;
child1List: any;
child2List: any;
currentUrl: string; // Store the current URL

DBmenuList: DataItem[] = [
// ... (existing menu items)
];

constructor(
private cdr: ChangeDetectorRef,
private menuService: MenuService,
private router: Router, // Inject the router
@Inject(DOCUMENT) document: Document
) {
document.getElementById("kt_app_sidebar_menu")?.click();

// Subscribe to NavigationEnd events to update the active menu item on route changes
this.subscriptions.push(
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe((event: NavigationEnd) => {
this.currentUrl = event.urlAfterRedirects;
this.setActiveMenu();
})
);
}

ngOnInit(): void {
this.getDBmenuList();
console.log("menuList", this.DBmenuList);

// Get the current URL on component initialization
this.currentUrl = this.router.url;
this.setActiveMenu();
}

getDBmenuList() {
this.ParentMenuList = this.DBmenuList.filter((w) => w.PARENT_MENU_ITEM_ID == 0);
}

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);
}

setActiveMenu() {
// Loop through menu items and set the active property based on the current URL
this.DBmenuList.forEach((item) => {
item.active = this.currentUrl.includes(item.MENU_URL);
});
}

ngOnDestroy() {
this.subscriptions.forEach((sb) => sb.unsubscribe());
}
}


Update sidebar-menu.component.html:


<!-- ... (existing code) -->

<div class="menu-item menu-accordion" data-kt-menu-trigger="click" (click)="expandMenu()" [ngClass]="{ "here": item.active }">
<!-- ... (existing code) -->
</div>

<!-- ... (existing code) -->


In this modification:

- We use the Router service to subscribe to NavigationEnd events, which occur when the route changes.
- The setActiveMenu method is called on initialization and every time the route changes. It loops through the menu items and sets the active property based on whether the current URL includes the menu item's URL.
- The ngClass directive in the HTML is used to conditionally apply the 'here' class to the menu item if it is active.

Please adjust the code according to your specific needs and styling conventions. This approach should help maintain the expanded state of the menu based on the current URL.



Hi,

You give html click event (click)="expandMenu()" but did not give typescript code.

You did not give routerLinkActive="here"

if it is okay

<div class="menu-item menu-accordion" data-kt-menu-trigger="click"
(click)="expandMenu()" [ngClass]="{'here': item.active }">


Please give me expandMenu() typescript method

Thanks


Deleted comment

Hi,

Please give the answer.

You give html click event (click)="expandMenu()" but did not give typescript code.

You did not give routerLinkActive="here"

if it is okay

<div class="menu-item menu-accordion" data-kt-menu-trigger="click"
(click)="expandMenu()" [ngClass]="{'here': item.active }">

Please give me expandMenu() typescript method

Thanks



Hi,

You can use the routerLinkActive directive to detect the active menu. This helps in maintaining the correct state of the menu, whether it should be minimized or not.

Here's how you can modify your code:

In the parent menu, add the routerLinkActive directive with a class that represents the active state:

<div class="menu-item menu-accordion" data-kt-menu-trigger="click" routerLinkActive="here">
<!-- Your menu content here -->
</div>

In the child menu, you can similarly use the routerLinkActive directive to detect the active state and apply a class (e.g., "active") accordingly:

<a class="menu-link without-sub" routerLinkActive="active" routerLink="/admin/subjectentry">
<!-- Your menu link content here -->
</a>

Make sure you have the corresponding styles for the "here" and "active" classes in your CSS to define the appearance of the active menu state.

This way, the menu will maintain its minimized or expanded state based on the active route, preventing it from being minimized on refresh.

Check here for more information:
https://angular.io/api/router/RouterLinkActive

Thanks



Hi,
Thanks for your reply. But it didn't work.


Here's html code:


<!--begin::Menu wrapper-->
<div

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"

data-kt-menu="true"
data-kt-menu-expand="false"
>
<!-- Pages -->
<ng-container>
<ng-container *ngFor="let item of ParentMenuList">
<div
class="menu-item menu-accordion"
data-kt-menu-trigger="click"
(click)="getChild1Menu(item.MENU_ITEM_ID)" routerLinkActive="here"
>
<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">
<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">
<!-- routerLinkActive="menu-active-bg" -->
<div
class="menu-sub menu-sub-accordion"
routerLinkActive="here"
>
<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>
</div>
<!--end::Menu-->
</div>
<!--end::Menu wrapper-->


here's typescript code:


import { M } from '@angular/cdk/keycodes';
import { DOCUMENT } from '@angular/common';
import { ChangeDetectorRef, Component, Inject, 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';
interface DataItem {
MENU_ITEM_ID: number;
PARENT_MENU_ITEM_ID: number;
MENU_DESCRIPTION: string;
MENU_URL: string;
}
@Component({
selector: 'app-sidebar-menu',
templateUrl: './sidebar-menu.component.html',
styleUrls: ['./sidebar-menu.component.scss'],
})
export class SidebarMenuComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
ParentMenuList: any;
child1List: any;
child2List: any;
DBmenuList: DataItem[] = [
{
MENU_ITEM_ID: 12,
PARENT_MENU_ITEM_ID: 0,
MENU_DESCRIPTION: 'Teacher',
MENU_URL: ''
},
{
MENU_ITEM_ID: 13,
PARENT_MENU_ITEM_ID: 12,
MENU_DESCRIPTION: 'Teacher Info',
MENU_URL: ''
},
{
MENU_ITEM_ID: 16,
PARENT_MENU_ITEM_ID: 13,
MENU_DESCRIPTION: 'Teacher Entry',
MENU_URL: 'teacher/teacher-entry'
},
{
MENU_ITEM_ID: 17,
PARENT_MENU_ITEM_ID: 13,
MENU_DESCRIPTION: 'Teacher Profile',
MENU_URL: 'teacher/teacher-profile'
},
{
MENU_ITEM_ID: 14,
PARENT_MENU_ITEM_ID: 0,
MENU_DESCRIPTION: "Student",
MENU_URL: ''
},
{
MENU_ITEM_ID: 15,
PARENT_MENU_ITEM_ID: 14,
MENU_DESCRIPTION: "Student Information",
MENU_URL: ''
},
{
MENU_ITEM_ID: 19,
PARENT_MENU_ITEM_ID: 15,
MENU_DESCRIPTION: "Quick Admission Info",
MENU_URL: "student/quickadmissioninfo"
},
{
MENU_ITEM_ID: 20,
PARENT_MENU_ITEM_ID: 15,
MENU_DESCRIPTION: "Student Bulk Entry",
MENU_URL: "student/studentbulkentry"
}
];
constructor(
private cdr: ChangeDetectorRef,
private menuService: MenuService,
@Inject(DOCUMENT) document: Document
) {
document.getElementById('kt_app_sidebar_menu')?.click();
}

ngOnInit(): void {

this.getDBmenuList();
console.log('menuList', this.DBmenuList);
}
getDBmenuList() {
this.ParentMenuList = this.DBmenuList.filter(
(w) => w.PARENT_MENU_ITEM_ID == 0
);
}
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
);
}
ngOnDestroy() {
this.subscriptions.forEach((sb) => sb.unsubscribe());
}
}


We already have routerlinkactive

but when we click the menu, it appears ok
https://ibb.co/Z1mtCpN

when we refresh the page:

https://ibb.co/n831BX6

menu is minimized.

But when we expand the menu it shows menu active
https://ibb.co/ZG3w9Y6

Please give us the solution.

For your convenience, I paste the html and ts code with json array instead of database.

Thanks.

Apologies for the delay, we have missed your reply, and thank you for your patience. To address your request, please follow these instructions:

In the file /demo1/src/app/_metronic/layout/layout.component.ts, add the following code within the ngOnInit() function:

ngOnInit() {
document.body.setAttribute("data-kt-app-sidebar-minimize", "on");
}


This code will set the attribute data-kt-app-sidebar-minimize to 'on' for the body element. If you have any further questions or concerns, feel free to ask.



Thanks for your reply. But this was not my query.
When I click a menu, it is okay:
https://ibb.co/qn2Z3G7
But when I reload the page: menu is minimized:
https://ibb.co/kmkv1b0

Please give a solution



Hi,

May I know which demo are you working on?

THanks



Hi,

Demo1 angular theme.

Thanks


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  :(