I've run into a strange to me issue that I'm not sure how to solve correctly. I'm using Bootstap 5. Let me provide a small example:
const reportBtns = Array.from(document.querySelectorAll('.report'))
reportBtns.forEach((btn) => {
btn.addEventListener('click', () => {
const myModal = new bootstrap.Modal(document.getElementById('testModal'))
myModal.show()
const modalBtn = document.querySelector('.btn-submit')
modalBtn.addEventListener('click', (e) => {
console.log('clicked')
})
})
})
.report:hover {
cursor: pointer;
}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<ul>
<li class="report">
<span>Report</span>
</li>
<li class="report">
<span>Report</span>
</li>
<li class="report">
<span>Report</span>
</li>
</ul>
<div class="modal" tabindex="-1" id="testModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-submit">Submit</button>
</div>
</div>
</div>
</div>
So, when I click Submit for the first time in my console I see clicked
logged one time, however, when I close the modal, open it again and click Submit for the second time, I see clicked
logged three times instead of two. Next time it will be 6 clicked
and so on. I kind of understand that the reference to old modals is kept for some reason, and when I click Submit
on a new modal previous modals are submitting too.
It doesn't make any sense to me why it is happening. I tried using modal.dispose()
when modal was closed , but it didn't work, and I'm not even sure if I was using it correctly or it's been used for this purpose.
reportBtns.forEach((btn) => {
btn.addEventListener('click', async () => {
const myModal = new bootstrap.Modal(document.getElementById('testModal'))
myModal.show()
const modalRef = document.querySelector('#testModal')
modalRef.addEventListener('hidden.bs.modal', function () {
const modal = bootstrap.Modal.getInstance(modalRef)
if (modal) {
modal.dispose()
}
})
const modalBtn = document.querySelector('.btn-submit')
modalBtn.addEventListener('click', (e) => {
console.log('clicked')
})
})
})
I'd appreciate your help.
You add an event listener everytime the 'Report' button is clicked, yet you forgot to remove the event listener after the modal closes. The number of event listeners "stack up," and eventually multiple event listeners are fired when the submit button is clicked, causing it to log it multiple times.
I recommend adding an event listener to all buttons using querySelectorAll
and a for
loop once.
const reportBtns = Array.from(document.querySelectorAll('.report'))
reportBtns.forEach((btn) => {
btn.addEventListener('click', () => {
const myModal = new bootstrap.Modal(document.getElementById('testModal'))
myModal.show()
})
})
const modalBtns = document.querySelectorAll('.btn-submit')
for (let i = 0; i < modalBtns.length; i++) {
modalBtns[i].addEventListener('click', (e) => {
console.log('clicked')
})
}
.report:hover {
cursor: pointer;
}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<ul>
<li class="report">
<span>Report</span>
</li>
<li class="report">
<span>Report</span>
</li>
<li class="report">
<span>Report</span>
</li>
</ul>
<div class="modal" tabindex="-1" id="testModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-submit">Submit</button>
</div>
</div>
</div>
</div>