modal open with javascript, not close correctly
Describe the bug if open modal with javascript, i can't close modal with javascript helper or data-modal-toggle=""
To Reproduce Steps to reproduce the behavior:
- Go to official site: https://flowbite.com/docs/components/modal/#methods
- open modal with javascript from chrome console
-
new Modal(document.getElementById('defaultModal'), null).show(); - Close modal with (X) icon inside modal, not close modal!
- no javscript error
Expected behavior close correctly modal
Screenshots

Desktop (please complete the following information):
- OS: Ubuntu
- Browser chrome
- Version 1.4.1
Smartphone (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
Additional context Add any other context about the problem here.
Hey @KinG-InFeT,
If you use the object methods you need to add the event listeners yourself on the close icon to close the same instance of the Modal.
For example:
const modal = new Modal(document.getElementById('defaultModal'), null).show();
const icon = document.getElementById('close-icon');
icon.addEventListener('click', () => {
modal.hide();
})
hi @zoltanszogyenyi , thank you for reply, after hide, the background continue to appair
@zoltanszogyenyi zoltanszogyenyi the background is: modal-backdrop not removed by javascript
@zoltanszogyenyi i resolve my problem with small javascript code (very very simple) with jquery
$('[data-modal-toggle]').on('click', function (event) {
var modal_id = $(this).data("modal-toggle");
if($('#'+modal_id).hasClass("hidden")) {
$('[modal-backdrop]').remove();
}
});
Hi guys.
Coming from bootstrap modals (pure HTML and Vue), this seems hacky. If I initialize the modal via JS, and toggle it via JS, and then click on a button with data-modal-toggle, the background stays on.
modal = new Modal(targetEl, options);
modal.show();
<button type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"
data-modal-toggle="{{$id}}">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</button>

I ended up using custom data-modal-hide and data-modal-show to make this work. Too bad though the toggle doesn't work :/
Alright so looking at the sourcecode, it seems like the lib is automatically creating an instance of the modal via the data-modal-toggle attribute, and then manually creating the modal via custom JS creates another instance of the same modal.
Are there any instructions on how to toggle a modal in the JS without re-creating a new modal instance? Could we have the getModalInstance exposed so we can use it to programatically change the modal visibility?
I am having also the same issue, the modal is created with js and when it is closed through any button the backdrop stays on. Didn't understood @michelvermeulen solution with data-modal-hide and data-modal-show.
I've just pushed a pull request to add an attribute so modals can be opened by default, without the need for any JS. Fingers crossed it accepted. https://github.com/themesberg/flowbite/pull/141
@csoutham merged the PR. I think it's safe to close this issue :)
@csoutham merged the PR. I think it's safe to close this issue :)
hello, the PR however does not solve the problem in the ticket, it only helps not to open the modal via javascript, avoiding the basic problem. I believe the bug will still have to be fixed.
any update?
Same problem
Same problem
Same for me
Same here
Same problem here
Hey everyone,
When opening the modal with JavaScript, please use the modal.hide(); method by manually adding the event listener to the close button.
The data-modal-toggle will only work when the modal is initialized only via the data attributes.
Here's an example:
// set the modal menu element
const targetEl = document.getElementById('modalEl');
// options with default values
const options = {
placement: 'bottom-right',
backdropClasses: 'bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40',
onHide: () => {
console.log('modal is hidden');
},
onShow: () => {
console.log('modal is shown');
},
onToggle: () => {
console.log('modal has been toggled');
}
};
Create a new Modal object:
/*
* targetEl: required
* options: optional
*/
const modal = new Modal(targetEl, options);
Use these methods to show or hide the modal:
// show the modal
modal.show();
// hide the modal
modal.hide();
So in this case you can do something like:
<button id="close-modal">x</button>
Then do this:
document.getElementById('close-modal').addEventListener('click', function () {
modal.hide();
})
Read more about the Modal JS usage on Flowbite.
Hey everyone,
When opening the modal with JavaScript, please use the
modal.hide();method by manually adding the event listener to the close button.The
data-modal-togglewill only work when the modal is initialized only via the data attributes.Here's an example:
// set the modal menu element const targetEl = document.getElementById('modalEl'); // options with default values const options = { placement: 'bottom-right', backdropClasses: 'bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40', onHide: () => { console.log('modal is hidden'); }, onShow: () => { console.log('modal is shown'); }, onToggle: () => { console.log('modal has been toggled'); } };Create a new Modal object:
/* * targetEl: required * options: optional */ const modal = new Modal(targetEl, options);Use these methods to show or hide the modal:
// show the modal modal.show(); // hide the modal modal.hide();So in this case you can do something like:
<button id="close-modal">x</button>Then do this:
document.getElementById('close-modal').addEventListener('click', function () { modal.hide(); })Read more about the Modal JS usage on Flowbite.
hello, unfortunately we still do not understand the basic problem. use javascript to close the modal we agree, but if you open it with a normal toggle from a button and then you want to manage the closure with javascript, the reference to "modal" is lost (not to mention the possibility of having more modals open at the same time, how do you manage the reference? the problem still has not been solved and the management of events and the library should be improved to give the possibility to manage the modal in both ways (the correct motion in the management of the modal is exactly as bootstrap does https://getbootstrap.com/docs/5.2/components/modal/). in a nutshell, the backdrop must have the reference to the modal in some way, to be able to fully manage it!
Hey everyone, When opening the modal with JavaScript, please use the
modal.hide();method by manually adding the event listener to the close button. Thedata-modal-togglewill only work when the modal is initialized only via the data attributes. Here's an example:// set the modal menu element const targetEl = document.getElementById('modalEl'); // options with default values const options = { placement: 'bottom-right', backdropClasses: 'bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40', onHide: () => { console.log('modal is hidden'); }, onShow: () => { console.log('modal is shown'); }, onToggle: () => { console.log('modal has been toggled'); } };Create a new Modal object:
/* * targetEl: required * options: optional */ const modal = new Modal(targetEl, options);Use these methods to show or hide the modal:
// show the modal modal.show(); // hide the modal modal.hide();So in this case you can do something like:
<button id="close-modal">x</button>Then do this:
document.getElementById('close-modal').addEventListener('click', function () { modal.hide(); })Read more about the Modal JS usage on Flowbite.
hello, unfortunately we still do not understand the basic problem. use javascript to close the modal we agree, but if you open it with a normal toggle from a button and then you want to manage the closure with javascript, the reference to "modal" is lost (not to mention the possibility of having more modals open at the same time, how do you manage the reference? the problem still has not been solved and the management of events and the library should be improved to give the possibility to manage the modal in both ways (the correct motion in the management of the modal is exactly as bootstrap does https://getbootstrap.com/docs/5.2/components/modal/). in a nutshell, the backdrop must have the reference to the modal in some way, to be able to fully manage it!
This exactly.
Hi guys.
Coming from bootstrap modals (pure HTML and Vue), this seems hacky. If I initialize the modal via JS, and toggle it via JS, and then click on a button with data-modal-toggle, the background stays on.
modal = new Modal(targetEl, options); modal.show();<button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-toggle="{{$id}}"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path> </svg> </button>I ended up using custom data-modal-hide and data-modal-show to make this work. Too bad though the toggle doesn't work :/
Can you share the code you used to get around this issue please?
Can you share the code you used to get around this issue please?
simple, this is an example code to get the problem out: https://jsfiddle.net/2jkws153/
any update ?
Hey everyone,
I'll get on this for the next update in the next two weeks.
I agree with the general idea so we'll provide a fix for this.
Thanks for your patience!
PS: if anyone wants to contribute they are more than welcome. The code can be found inside the modal.js file.
new demo with latest css and js version: https://jsfiddle.net/vincenzo_hpo/z9scjduf/ , bug persist with v1.5.1
Hi guys,
a quick fix for me, so hope it help you too
onHide: () => {
console.log('modal is hidden');
document.querySelector('[modal-backdrop]').remove();
},
Hi everyone, I'm facing this issue and I'm proposing a fix here https://github.com/themesberg/flowbite/pull/274.
Still facing this issue. Anyone with a fix without involving JQuery?
Hi guys,
a quick fix for me, so hope it help you too
onHide: () => { console.log('modal is hidden'); document.querySelector('[modal-backdrop]').remove(); },
@yaqshank92 see this comment, use onHide event without jquery
Hey everyone,
I know that this has been long overdue, but with the v1.6.0 update and introducing TypeScript I have finally addressed this issue by changing the data-modal-toggle to data-modal-target which will be initialised only once, and the you can use data-modal-toggle/show/hide={modalId} to search for the modal instance and toggle, show or hide it.
Here's a breakdown of the code that does this:
const getModalInstance = (id: string, instances: ModalInstance[]) => {
if (instances.some((modalInstance) => modalInstance.id === id)) {
return instances.find((modalInstance) => modalInstance.id === id);
}
return null;
};
export function initModals() {
const modalInstances = [] as ModalInstance[];
document.querySelectorAll('[data-modal-target]').forEach(($triggerEl) => {
const modalId = $triggerEl.getAttribute('data-modal-toggle');
const $modalEl = document.getElementById(modalId);
const placement = $modalEl.getAttribute('data-modal-placement');
const backdrop = $modalEl.getAttribute('data-modal-backdrop');
if (!getModalInstance(modalId, modalInstances)) {
modalInstances.push({
id: modalId,
object: new Modal(
$modalEl as HTMLElement,
{
placement: placement ? placement : Default.placement,
backdrop: backdrop ? backdrop : Default.backdrop,
} as ModalOptions
),
});
}
});
document.querySelectorAll('[data-modal-toggle]').forEach(($triggerEl) => {
const $targetEl = document.getElementById(
$triggerEl.getAttribute('data-modal-toggle')
);
const modalId = $targetEl.id;
const modal: ModalInstance = getModalInstance(modalId, modalInstances);
if (modal) {
$triggerEl.addEventListener('click', () => {
modal.object.toggle();
});
}
});
document.querySelectorAll('[data-modal-show]').forEach(($triggerEl) => {
const $targetEl = document.getElementById(
$triggerEl.getAttribute('data-modal-show')
);
const modalId = $targetEl.id;
const modal: ModalInstance = getModalInstance(modalId, modalInstances);
if (modal) {
$triggerEl.addEventListener('click', () => {
if (modal.object.isHidden) {
modal.object.show();
}
});
}
});
document.querySelectorAll('[data-modal-hide]').forEach(($triggerEl) => {
const $targetEl = document.getElementById(
$triggerEl.getAttribute('data-modal-hide')
);
const modalId = $targetEl.id;
const modal: ModalInstance = getModalInstance(modalId, modalInstances);
if (modal) {
$triggerEl.addEventListener('click', () => {
if (modal.object.isVisible) {
modal.object.hide();
}
});
}
});
}
The update will arrive shortly and unfortunately we will have some breaking changes because data-modal-toggle will no longer initialise a modal object, only data-modal-target. The code will not break though.
This also fixed stacking up the event listeners for when click outside of the modal + escape button.
The functionality can be tested on this branch: https://github.com/themesberg/flowbite/tree/1.6.0
// show the modal modal.show();
creating a modal object with options and using modal.show() and modal.hide() instead of the default data-modal-toggle, worked for me, tnks :D