A list may contain many repeated controls, and new rows may be added after the page loads. Instead of attaching a listener to every button, listen on their shared parent and identify the activated control.
list.addEventListener("click", (event) => {
if (!(event.target instanceof Element)) return;
const button = event.target.closest("button[data-action]");
if (!button || !list.contains(button)) return;
handleAction(button.dataset.action, button.dataset.id);
});Keep the target check specific
- Use closest so clicks on an icon inside a button still reach that button.
- Confirm the match belongs to the intended list before acting.
- Keep action data on the control that owns the action.
Do not delegate everything
A direct listener is simpler for a small, stable set of controls or when each item needs distinct setup. Delegation is most useful when items repeat or are created dynamically.
Test clicks on nested content, keyboard activation, and controls outside the list. The event handler should respond once to the intended action and ignore unrelated clicks.
