KTComponents.init() specific component!
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
Replies (5)
Hi
here’s what’s happening and how to address it:
-
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.
-
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.
-
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);
}
This is the official way to re-initialize a menu on dynamic content.
-
You should not need to manually add click handlers or set positioning if the HTML and data attributes are correct and no other JS is interfering.
-
If you still need manual handlers, double-check: The menu’s parent/trigger structure matches the official demo. No custom or third-party JS is interfering with event propagation. There are no JavaScript errors in the console.
If you need further help, just let us know
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 = ` ` $('#divbtnmessage' + patientagenda).html(html)
In order to work I had to do this:
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';
}
});
}
So if that could be more simple it could be awesome