I’m using Metronic with Laravel + Livewire, and everything works fine in general.
I have an accordion placed inside a Livewire component that renders as a modal. The issue is: when I open the modal, the built-in KTUI accordion JS does not work.
Do I need to reinitialize KTUI when the modal is opened, or is there another recommended approach to make the accordion work inside dynamically rendered modals? If I need to reinitialize KTUI, how can I do it?
Hi Adam Nielsen
Here is one of the approaches without a timeout delay.
Use livewire built-in event.
document.addEventListener("livewire:init", function () {
// Main hook for DOM updates
Livewire.hook("morph.updated", ({ component, el }) => {
// Check if the updated element is a modal or contains a modal
const modal = el.querySelector("[data-kt-modal-initialized]") ||
(el.hasAttribute("data-kt-modal-initialized") ? el : null);
if (modal) {
const selectElements = modal.querySelectorAll("[data-kt-select]");
selectElements.forEach(el => {
// Dispose existing instance
if (el.instance) el.instance.dispose();
// Determine multiple state
const multiple = el.getAttribute("data-multiple") === "true";
// Create new instance with dynamic configuration
el.instance = new KTSelect(el, {
multiple: multiple,
displaySeparator: multiple ? " | " : undefined
});
});
}
});
});
<select
class="kt-select"
data-kt-select="true"
data-multiple="true" <!-- This will be read by the js -->
And can I disable / enable
multiple
data-kt-select-multiple="true"
data-kt-select-config="{
"displaySeparator": " | "
}"
Hey Faizal, thanks for your suggestion. I tried that, and it seems that
const selectElements = modal.querySelectorAll("[data-kt-select]");
document.addEventListener("shown", () => {
setTimeout(() => {
const modal = document.querySelector("[data-kt-modal-initialized]");
const selectElements = modal.querySelectorAll("[data-kt-select]");
selectElements.forEach(el => {
if (el.instance) el.instance.dispose();
el.instance = new KTSelect(el);
});
}, 50);
});
Hi Adam Nielsen
Here's the correct solution for reinitializing KTSelect components in Livewire modals:
document.addEventListener("livewire:init", function () {
// Listen for the actual KTUI modal "shown" event
document.addEventListener("shown", function(event) {
// Check if this is a modal event
if (event.target.hasAttribute("data-kt-modal-initialized")) {
const modal = event.target;
// Find uninitialized select elements in the modal
const selectElements = modal.querySelectorAll("[data-kt-select]");
selectElements.forEach(element => {
// Check if the element already has a KTSelect instance
if (element.instance) {
// Dispose the existing instance first
element.instance.dispose();
}
// Create a new KTSelect instance
new KTSelect(element);
});
}
});
});
Hey Faizal, this works perfect thank you.
I have the same issue with a multiple select
<select
class="kt-select"
data-kt-select="true"
data-kt-select-multiple="true"
data-kt-select-max-selections="3"
data-kt-select-placeholder="Select cities..."
data-kt-select-config="{
"displaySeparator": " | "
}"
>
<option value="amsterdam">Amsterdam</option>
<option value="barcelona">Barcelona</option>
<option value="london">London</option>
<option value="new-york">New York</option>
<option value="paris">Paris</option>
<option value="rome">Rome</option>
<option value="tokyo">Tokyo</option>
</select>
<div>
<x-modal :title="$edit_mode ? __("Edit AI Model") : __("Create AI Model")">
<select
class="kt-select"
data-kt-select="true"
data-kt-select-multiple="true"
data-kt-select-max-selections="3"
data-kt-select-placeholder="Select cities..."
data-kt-select-config="{
"displaySeparator": " | "
}"
>
<option value="amsterdam">Amsterdam</option>
<option value="barcelona">Barcelona</option>
<option value="london">London</option>
<option value="new-york">New York</option>
<option value="paris">Paris</option>
<option value="rome">Rome</option>
<option value="tokyo">Tokyo</option>
</select>
</x-modal>
</div>
<script>
document.addEventListener("livewire:init", function () {
console.log("init")
// Listen for the actual KTUI modal "shown" event
document.addEventListener("shown", function(event) {
if (event.target.hasAttribute("data-kt-modal-initialized")) {
const modal = event.target;
// Find uninitialized accordions in the modal
const selectboxes = modal.querySelectorAll("[data-kt-select]:not([data-kt-select-initialized])");
console.log(accordions);
selectboxes.forEach(element => {
let x = new KTSelect(element);
console.log(x);
});
}
});
});
</script>
Hi Adam Nielsen
Sorry, could you please try this code to reinitialize accordion in livewire, after opening modal?
document.addEventListener("livewire:init", function () {
// Listen for the actual KTUI modal "shown" event
document.addEventListener("shown", function(event) {
// Check if this is a modal event
if (event.target.hasAttribute("data-kt-modal-initialized")) {
const modal = event.target;
// Find uninitialized accordions in the modal
const accordions = modal.querySelectorAll("[data-kt-accordion]:not([data-kt-accordion-initialized])");
accordions.forEach(element => {
new KTAccordion(element);
});
}
});
});
Hi Adam Nielsen
Yes, you need to reinitialize KTUI components after Livewire updates the DOM.
// After Livewire updates
Livewire.hook("message.processed", (message, component) => {
// Re-initialize all KTUI components
KTComponents.init();
});
// If using Bootstrap modals
document.addEventListener("shown.bs.modal", function(event) {
const modal = event.target;
const accordions = modal.querySelectorAll("[data-kt-accordion]");
accordions.forEach(element => {
if (!element.hasAttribute("data-kt-accordion-initialized")) {
new KTAccordion(element);
}
});
});
Hey thank you. I am using Tailwind. Unfortunately, the
Livewire.hook("message.processed", (message, component) => {
// Re-initialize all KTUI components
console.log("hallo");
KTComponents.init();
});
<pre lang="html">
<x-modal>
@if($user)
<x-accordion >
@endif
</x-modal>
<pre lang="html">
<div>
<livewire:modal>
</div>
@push("scripts")
<script>
document.addEventListener("DOMContentLoaded", function () {
Livewire.hook("message.processed", (message, component) => {
// Re-initialize all KTUI components
KTComponents.init();
});
</script>
@endpush
Livewire.on("open-info-modal", () => {
console.log("reinit mtgf");
KTComponents.init();
});