Is there a way to initialize specific component, I work with dynamic generated components, so if I use KTComponents.init() will conflict with already created components and stop working, so I was trying to initialize a [data-kt-menu] and using new KTMenu(menuTrigger) doesn't initialize completely as all click functionality not working properly
I'm working with javascript
Hi
here’s what’s happening and how to address it:
1. The menu system relies on both the correct markup and the presence of certain data attributes (like data-kt-menu, data-kt-menu-item-trigger, etc.).
If your injected HTML is missing these, the menu will not behave fully.
2. If you only create a new instance with new KTMenu(element), the global event handlers may not be attached if they were never initialized on the page.
3. How to fix this without resetting all components:
You need to call KTMenu.initHandlers() once per page load.
This attaches the global event handlers for all menus, including dynamically created ones.
// 1. On first page load (or after Metronic assets are loaded), call this ONCE:
if (!window.KT_MENU_INITIALIZED) {
KTMenu.initHandlers();
window.KT_MENU_INITIALIZED = true;
}
// 2. When you inject a new menu:
var menuTrigger = document.querySelector(`#divbtnmessage${patientagenda} [data-kt-menu-trigger]`);
if (menuTrigger) {
var existingInstance = KTMenu.getInstance(menuTrigger);
if (existingInstance) {
existingInstance.destroy();
}
new KTMenu(menuTrigger);
}
Hi David Polanco
Currently, Metronic does not provide a built-in way to initialize only a specific component with KTComponents.init(). The recommended approach for dynamic content is:
- Destroy any existing KTMenu instance before re-initializing:
var menuTrigger = document.querySelector(`#divbtnmessage${patientagenda} [data-kt-menu-trigger]`);
if (menuTrigger) {
var existingInstance = KTMenu.getInstance(menuTrigger);
if (existingInstance) {
existingInstance.destroy();
}
var newInstance = new KTMenu(menuTrigger);
}
I try only that code but the issue persist as doesn't work entirely it can show visually the menu but the behavior and submenu not, this is why I have to include more code for the click and the submenu itself and position on page.
If you see the code I provide had extra as your code
// Add click handler with fixed positioning
// Handle clicking outside to close
If I use only KTComponents.init() works perfectly but it will reset all my current components, and for the behaviour of my page I can't do that...
Hi David Polanco
Are you using the HTML version, or is this within a framework (React, Vue, etc.)?
Can you provide a code snippet of how you are generating the dynamic menu and initializing it?
Thanks
HTML version, I have a function depending behavior I do:
var html = `<div class="d-flex cursor-pointer" data-kt-menu-trigger="{default: "click", lg: "click"}" data-kt-menu-attach="parent" data-kt-menu-placement="bottom-start" data-kt-menu-offset="0px, 5px">
<a class="position-relative mt-1 text-hover-primary cursor-pointer">
<i class="fa-duotone fa-solid fa-calendar-check text-primary fs-2"></i>
</a>
</div>
<!--begin::User account menu-->
<div class="menu menu-sub menu-sub-dropdown menu-column fs-6 w-300px" data-kt-menu="true">
<!--begin::Heading-->
<div class="d-flex flex-column bgi-no-repeat rounded-top px-3 py-2" >
<!--begin::Title-->
<div class="menu-item px-3 text-white">Calendario</div>
<!--end::Title-->
</div>
<!--end::Heading-->
<!--begin::Tab content-->
<div class="scroll-y mh-325px">
</div>
<div class="separator mb-2"></div>
<div class="pb-2 px-3 fs-8">
<!--begin::Tab panel-->
Modificar el Calendario
<!--end::Tab panel-->
</div>
</div>`
$("#divbtnmessage" + patientagenda).html(html)
var menuTrigger = document.querySelector(`#divbtnmessage${patientagenda} [data-kt-menu-trigger]`);
var menuDropdown = document.querySelector(`#divbtnmessage${patientagenda} .menu-sub`);
if (menuTrigger && menuDropdown) {
var existingInstance = KTMenu.getInstance(menuTrigger);
if (existingInstance) {
existingInstance.destroy();
}
var newInstance = new KTMenu(menuTrigger);
// Add click handler with fixed positioning
menuTrigger.addEventListener("click", function (e) {
setTimeout(function () {
if (menuTrigger.classList.contains("showing")) {
var rect = menuTrigger.getBoundingClientRect();
menuDropdown.style.display = "block";
menuDropdown.style.position = "fixed";
menuDropdown.style.top = (rect.bottom + 5) + "px";
menuDropdown.style.left = rect.left + "px";
menuDropdown.style.zIndex = "9999";
} else {
menuDropdown.style.display = "none";
}
}, 50);
});
// Handle clicking outside to close
document.addEventListener("click", function (e) {
if (!menuTrigger.contains(e.target) && !menuDropdown.contains(e.target)) {
menuDropdown.style.display = "none";
}
});
}