Event listeners not attaching after an operation on the page

Hello, for some reason when I use the search field or add a cyclist, the element gets added to the page but the show details and delete button doesnt work. They work on reload however. It's an even listener issue but I tried all sorts of things but doesnt seem to be working. This are the buttons:
<button sec:authorize="hasAnyRole('ADMIN','USER')" th:text="#{cyclist.text13}" class="btn btn-primary show-details-btn"
th:data-target="'#cyclistDetailsModal_' + ${cyclist.id}" data-toggle="modal"><i class="bi bi-eye-fill"></i> Show Details
</button>
<button type="button" class="btn btn-danger delete-cyclist-btn" th:attr="data-cyclist-id=${cyclist.id}">
<i class="bi bi-trash-fill"></i> Delete
</button>
<button sec:authorize="hasAnyRole('ADMIN','USER')" th:text="#{cyclist.text13}" class="btn btn-primary show-details-btn"
th:data-target="'#cyclistDetailsModal_' + ${cyclist.id}" data-toggle="modal"><i class="bi bi-eye-fill"></i> Show Details
</button>
<button type="button" class="btn btn-danger delete-cyclist-btn" th:attr="data-cyclist-id=${cyclist.id}">
<i class="bi bi-trash-fill"></i> Delete
</button>
No description
24 Replies
Aman
Amanβ€’2mo ago
Aman
Amanβ€’2mo ago
import { handleDeleteCyclistEvent, showDetailsEvent, attachSearchCyclistListener } from './handlers.js';

export function initializeEventListeners() {
attachEventListeners('.delete-cyclist-btn', 'click', handleDeleteCyclistEvent);
attachEventListeners('.show-details-btn', 'click', showDetailsEvent);
attachSearchCyclistListener();
}

export function attachEventListeners(selector, event, handler) {
document.querySelectorAll(selector).forEach(element => element.addEventListener(event, handler));
}

document.addEventListener("DOMContentLoaded", initializeEventListeners);
import { handleDeleteCyclistEvent, showDetailsEvent, attachSearchCyclistListener } from './handlers.js';

export function initializeEventListeners() {
attachEventListeners('.delete-cyclist-btn', 'click', handleDeleteCyclistEvent);
attachEventListeners('.show-details-btn', 'click', showDetailsEvent);
attachSearchCyclistListener();
}

export function attachEventListeners(selector, event, handler) {
document.querySelectorAll(selector).forEach(element => element.addEventListener(event, handler));
}

document.addEventListener("DOMContentLoaded", initializeEventListeners);
this is all the code concerning this issue
Chooβ™šπ•‚π•šπ•Ÿπ•˜
If attachEventListeners() is the only code that adds event listeners, and it only gets called upon loading of the page, that won't include any new items added later. So the problem is that you are not also adding event listeners immediately after new elements are created.
clevermissfox
clevermissfoxβ€’2mo ago
Might be a good case for a JavaScript class
class Cyclist (){
constructor(id, name, age, nationality, height)
this.id = id
//etc etc
}
class Cyclist (){
constructor(id, name, age, nationality, height)
this.id = id
//etc etc
}
Aman
Amanβ€’2mo ago
This is not needed bc I have this class in my Spring application. Js is used for adding, updating, searching and deleting records without page refresh. So what you are saying is that when i search something, I should also attach the listeners? And not just on a page load?
clevermissfox
clevermissfoxβ€’2mo ago
Why not have the event listeners in the class if they all have the same buttons ?
Aman
Amanβ€’2mo ago
Im not sure if its even possible to have listeners in Java spring application
clevermissfox
clevermissfoxβ€’2mo ago
Ok Idk what a spring application is then just add event listeners scoped to the buttons you need
Chooβ™šπ•‚π•šπ•Ÿπ•˜
What I am saying is the event listeners must be attached to all new elements in the DOM that you expect to respond to user interaction. This must be done regardless of the reason that the new elements are being added. It doesn't matter if it's because of search or some other reason.
Aman
Amanβ€’2mo ago
is a framework for the Java platform
Chooβ™šπ•‚π•šπ•Ÿπ•˜
You could also use event delegation. That would involve placing an event listener only on the container and checking the event target to determine which element the event happened on.
Aman
Amanβ€’2mo ago
I will try it now. Can I get back to you if it doesnt work?
clevermissfox
clevermissfoxβ€’2mo ago
It will work, event delegation is what you need. That’s the proper word for what I said about an event listener scoped to the buttons. Add it on the container, like say the ul that holds each li row . Then:
if(!e.target.closest(β€˜button’) return
if (e.target.closest(β€˜.show-details-btn’) {//show details handler }
if (e.target.closest(β€˜.delete-cyclist-btn’) {//delete handler}
if(!e.target.closest(β€˜button’) return
if (e.target.closest(β€˜.show-details-btn’) {//show details handler }
if (e.target.closest(β€˜.delete-cyclist-btn’) {//delete handler}
Etc Also from a quick google you can add event listeners on a class in Java Spring application but looks like a lot of code to create and publish @EventListener
Aman
Amanβ€’2mo ago
I reattached the listener when for example I search and table is loaded with new data but I just get this error message
data-target attribute is missing on the button element.
data-target attribute is missing on the button element.
export function showDetailsEvent(event) {
event.preventDefault();
const target = event.target.closest('.show-details-btn');
if (target) {
const dataTarget = target.getAttribute('data-target');
console.log('data-target:', dataTarget);
if (dataTarget) {
const cyclistId = dataTarget.split('_').pop();
showDetails(cyclistId);
} else {
console.error('data-target attribute is missing on the button element.');
}
}
}
function showDetails(cyclistId) {
const detailsModal = document.getElementById('cyclistDetailsModal_' + cyclistId);
if (detailsModal) {
$(detailsModal).modal('show');
} else {
console.error(`Modal with ID cyclistDetailsModal_${cyclistId} not found.`);
}
}
export function showDetailsEvent(event) {
event.preventDefault();
const target = event.target.closest('.show-details-btn');
if (target) {
const dataTarget = target.getAttribute('data-target');
console.log('data-target:', dataTarget);
if (dataTarget) {
const cyclistId = dataTarget.split('_').pop();
showDetails(cyclistId);
} else {
console.error('data-target attribute is missing on the button element.');
}
}
}
function showDetails(cyclistId) {
const detailsModal = document.getElementById('cyclistDetailsModal_' + cyclistId);
if (detailsModal) {
$(detailsModal).modal('show');
} else {
console.error(`Modal with ID cyclistDetailsModal_${cyclistId} not found.`);
}
}
This is what I did
No description
Aman
Amanβ€’2mo ago
What's weird is that delete event listener works but not for show details
export function initializeEventListeners() {
attachEventListeners('.delete-cyclist-btn', 'click', handleDeleteCyclistEvent);
attachEventListeners('.show-details-btn', 'click', showDetailsEvent);
attachSearchCyclistListener();
reattachEventListeners();
}
export function initializeEventListeners() {
attachEventListeners('.delete-cyclist-btn', 'click', handleDeleteCyclistEvent);
attachEventListeners('.show-details-btn', 'click', showDetailsEvent);
attachSearchCyclistListener();
reattachEventListeners();
}
Want results from more Discord servers?
Add your server