Klik Anak Malah Menyalakan Induk? Cara Mengatasi Event Bubbling Javascript Tidak Diinginkan dengan stopPropagation

Panggil event.stopPropagation() di handler elemen anak untuk cara mengatasi event bubbling javascript tidak diinginkan. Tanpa itu, klik tombol di dalam card ikut menjalankan listener click milik card, modal, atau li karena event berjalan dari target ke atas.

Penyebab Event Bubbling Terpicu ke Elemen Induk

Browser menjalankan event dalam tiga fase: capturing turun dari window ke target, lalu target, lalu bubbling naik kembali ke induk. addEventListener memakai fase bubbling secara default.

Kasus umum yang sering bermasalah:

  • Tombol hapus di dalam card yang bisa diklik untuk membuka detail.
  • Tombol tutup atau konten di dalam modal yang klik backdrop-nya menutup modal.
  • Tombol kecil di dalam li atau form yang punya handler sendiri.

Tanda handler induk ikut jalan:

  • Klik tombol anak membuka detail card sekaligus menghapus item.
  • Klik isi modal malah menutup modal.
  • Satu klik memicu dua aksi berurutan, anak dulu lalu induk.

Tabel Kondisi, Penyebab, dan Solusi Cepat

Kondisi | Penyebab | Solusi

Klik tombol anak menjalankan aksi card | Event naik ke listener induk | Tambahkan stopPropagation() di handler anak

Klik isi modal menutup modal | Listener backdrop menerima bubble | Cek event.target atau hentikan bubble dari konten

Handler tidak jalan sama sekali | Selector salah atau DOM belum siap | Periksa querySelector setelah DOM dimuat, bukan logic propagasi

Cara Memperbaiki Event Bubbling yang Tidak Diinginkan

Ikuti urutan ini agar tidak salah memblokir event lain:

  1. Temukan listener induk yang ikut terpanggil, misalnya di .card.
  2. Cek event.target untuk elemen yang diklik dan event.currentTarget untuk elemen pemilik listener.
  3. Pasang stopPropagation() hanya di handler anak.
  4. Uji klik anak dan klik area induk secara terpisah.

Salah, klik tombol ikut membuka card:

document.querySelector(".card").addEventListener("click", () => {
  openDetail();
});
document.querySelector(".delete-btn").addEventListener("click", () => {
  deleteItem();
});

Benar, klik tombol berhenti di tombol:

document.querySelector(".delete-btn").addEventListener("click", (event) => {
  event.stopPropagation();
  deleteItem();
});

Pakai stopImmediatePropagation() bila satu elemen punya beberapa listener click dan listener berikutnya harus dibatalkan juga. Untuk daftar dinamis, pakai delegation dengan closest() agar satu listener di container bisa membedakan tombol anak dan area card.

Cara Mencegah Bubbling Kambuh di Elemen Dinamis

  • Pasang listener di container terdekat, bukan di document untuk semua hal.
  • Hindari listener ganda pada elemen yang dirender ulang, bersihkan dulu atau pakai delegation.
  • Pastikan DOM siap sebelum querySelector, panggil skrip di akhir body atau setelah DOMContentLoaded.
  • Gunakan textContent bila hanya butuh teks, karena lebih aman daripada innerHTML.

FAQ

Apakah stopPropagation menghentikan listener lain di elemen yang sama?

Tidak, gunakan stopImmediatePropagation() untuk menghentikan listener lain pada elemen yang sama.

Kapan memakai event.target dibanding event.currentTarget?

Pakai event.target untuk mengetahui elemen yang diklik, pakai event.currentTarget untuk elemen pemilik listener.

Apakah preventDefault bisa menghentikan bubbling?

Tidak, preventDefault() hanya membatalkan aksi bawaan browser dan event tetap naik ke induk.