Pendahuluan
Halo teman-teman developer! Senang sekali bisa bertemu lagi di artikel keenam dari seri pembuatan Aplikasi Kuis Interaktif kita. Pada artikel sebelumnya, kita sudah belajar cara melakukan manipulasi DOM (Document Object Model), seperti mengubah teks, mengganti warna, hingga menambah elemen baru ke dalam halaman HTML kita. Namun, ada satu hal yang masih kurang: aplikasi kita masih “diam”. Kita bisa mengubah isi halaman, tapi halaman tersebut tidak bereaksi terhadap apa pun yang dilakukan pengguna.
Bayangkan jika kamu sedang menggunakan aplikasi Gojek atau Tokopedia. Aplikasi tersebut terasa hidup karena setiap kali kamu menekan tombol “Pesan” atau menggeser (swipe) sebuah banner, ada aksi yang terjadi. Di dunia web development, aksi-aksi seperti klik, ketikan keyboard, atau gerakan mouse ini disebut sebagai Event.
Dalam tutorial kali ini, kita akan mempelajari jantung dari interaktivitas web, yaitu Event Listener dan Event Handling. Kita akan belajar bagaimana cara “mendengarkan” apa yang dilakukan pengguna pada aplikasi kuis kita, lalu memberikan respon yang sesuai—seperti mengecek apakah jawaban yang dipilih benar atau salah. Di akhir artikel ini, Aplikasi Kuis Interaktif kita akan benar-benar berfungsi secara penuh!
Apa itu Event dan Event Target?
Sebelum masuk ke kode, mari kita pahami konsep dasarnya. Dalam JavaScript, Event adalah sebuah sinyal yang dikirimkan oleh browser untuk memberitahu bahwa sesuatu telah terjadi. Kejadian ini bisa berupa interaksi pengguna atau perubahan pada status browser.
Beberapa jenis event yang paling sering kita temui adalah:
click: Terjadi ketika pengguna mengklik sebuah elemen.submit: Terjadi ketika sebuah form dikirimkan.keydown: Terjadi ketika pengguna menekan tombol di keyboard.mouseover: Terjadi ketika kursor mouse berada di atas sebuah elemen.
Lalu, apa itu Event Target? Event Target adalah elemen HTML yang menjadi pemicu terjadinya event tersebut. Jika kamu mengklik tombol “Mulai Kuis”, maka tombol tersebut adalah target-nya.
Sebagai analogi, bayangkan sebuah bel rumah. Ketika seseorang menekan tombol bel (ini adalah Event), bel tersebut berbunah. Tombol bel yang ditekan adalah Event Target. Tanpa adanya aksi (tekanan), tidak akan ada reaksi (bunyi).
Menggunakan addEventListener()
Di JavaScript, cara paling standar dan profesional untuk menangani event adalah dengan menggunakan metode .addEventListener(). Meskipun ada cara lama seperti menggunakan atribut onclick langsung di HTML, kita sangat tidak disarankan menggunakan cara tersebut karena akan membuat kode HTML dan JavaScript kita tercampur aduk (tidak rapi).
Metode addEventListener() memungkinkan kita untuk memasang satu atau lebih fungsi “pendengar” pada satu elemen yang sama tanpa menimpa fungsi yang sudah ada.
Berikut adalah contoh sederhana cara kerjala addEventListener:
// Mengambil elemen tombol dari DOM
const tombolBudi = document.querySelector('#btn-budi');
// Membuat fungsi yang akan dijalankan saat event terjadi
function sapaBudi() {
alert("Halo Budi! Selamat datang di kuis!");
}
// Memasang event listener pada tombol
// Parameter 1: Jenis event ('click')
// Parameter 2: Fungsi yang akan dijalitas (callback function)
tombolBudi.addEventListener('click', sapaBudi);
Dalam contoh di atas, saat elemen dengan ID btn-budi diklik, browser akan menjalankan fungsi sapaBudi. Kode ini sangat bersih dan mudah dikelola, mirip dengan bagaimana developer di perusahaan besar seperti BCA atau Mandiri menulis kode yang terstruktur.
Mengenal Event Object
Saat sebuah event terjadi, JavaScript secara otomatis mengirimkan sebuah objek spesial ke dalam fungsi handler kita. Objek ini disebut sebagai Event Object (seringkali kita singkat menjadi e atau event di dalam parameter fungsi).
Objek ini sangat kaya akan informasi. Ia menyimpan detail tentang apa yang terjadi, elemen mana yang diklik, bahkan koordinat mouse di layar. Salah satu properti yang paling penting adalah event.target, yang merujuk kembali ke elemen yang memicu event tersebut.
Mari kita lihat contoh penggunaan event.target untuk mendeteksi tombol mana yang diklik:
const containerJawaban = document.querySelector('.container-jawaban');
// Kita memasang listener pada parent (container), bukan pada tiap tombol
containerJawaban.addEventListener('click', function(e) {
// e.target akan berisi elemen yang sebenarnya diklik oleh user
const elemenYangDiklik = e.target;
// Kita cek apakah yang diklik adalah sebuah tombol jawaban
if (elemenYangDiklik.tagName === 'BUTTON') {
console.log("Kamu memilih jawaban: " + elemenYangDiklik.innerText);
console.log("ID Jawaban: " + elemenYangDiklik.id);
}
});
Teknik di atas disebut dengan Event Delegation. Ini adalah teknik tingkat lanjut yang sangat efisien karena kita tidak perlu memasang listener ke setiap tombol satu per satu, melainkan cukup ke induknya (container) saja. Ini sangat menghemat penggunaan memori browser.
Implementasi dalam Proyek: Aplikasi Kuis Interaktif
Sekarang, mari kita terapkan semua ilmu ini ke dalam proyek utama kita. Kita akan membuat logika di mana ketika pengguna mengklik salah satu pilihan jawaban, aplikasi akan mengecek apakah jawaban tersebut benar atau salah, lalu memberikan feedback visual.
Berikut adalah potongan kode JavaScript yang akan kita integrasikan ke dalam proyek kita:
// Data kuis (asumsi kita sudah punya dari langkah sebelumnya)
const pertanyaan = [
{
tanya: "Apa ibu kota Indonesia?",
opsi: ["Jakarta", "Bandung", "Surabaya", "Medan"],
jawabanBenar: "Jakarta"
}
s];
const containerPertanyaan = document.querySelector('#pertanyaan-container');
const containerOpsi = document.querySelector('#opsi-container');
// Fungsi untuk menampilkan pertanyaan
function tampilkanKuis() {
const data = pertanyaan[0]; // Kita ambil pertanyaan pertama
containerPertanyaan.innerText = data.tanya;
// Bersihkan opsi lama
containerOpsi.innerHTML = '';
// Membuat elemen tombol untuk setiap opsi
data.opsi.forEach((pilihan) => {
const button = document.createElement('button');
button.innerText = pilihan;
button.classList.add('btn-opsi');
// --- INI ADALAH INTI EVENT LISTENER ---
button.addEventListener('click', function(e) {
cekJawaban(e.target.innerText, data.jawabanBenar);
});
// --------------------------------------
containerOpsi.appendChild(button);
});
}
// Fungsi untuk mengecek jawaban
function cekJawaban(pilihanUser, jawabanBenar) {
if (pilihanUser === jawabanBenar) {
alert("Mantap! Jawaban kamu Benar! 🎉");
// Di sini kita bisa menambah skor atau lanjut ke soal berikutnya
} else {
alert("Yah, salah. Coba lagi ya! 😢");
}
}
// Jalankan fungsi saat pertama kali load
tampilkanKuis();
Dalam kode di atas, kita menggunakan forEach untuk membuat tombol secara dinamis. Di dalam loop tersebut, kita langsung memasang addEventListener pada setiap tombol yang baru dibuat. Jadi, setiap kali tombol diklik, fungsi cekJawaban akan dipanggil dengan membawa teks dari tombol tersebut sebagai argumen.
Kesalahan Umum
Selama belajar event handling, saya sering melihat junior developer terjebentar dalam beberapa error klasik. Berikut adalah 3 error yang paling sering muncul:
1. Menjalankan Fungsi Secara Langsung (Immediate Execution)
Pesan error:
(Tidak ada error di terminal, tapi fungsi berjalan otomatis saat halaman baru di-refresh)
Penyebab: Anda menuliskan tanda kurung () saat mendaftarkan function di addEventListener.
Solusi: Jangan gunakan tanda kurung jika tidak ada parameter yang dikirim.
Salah: element.addEventListener('click', myFunction());
Benar: element.addEventListener('click', myFunction);
2. Error “Cannot read property ‘addEventListener’ of null”
Pesan error: Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
Penyebab: Script JavaScript Anda berjalan sebelum elemen HTML selesai dibuat oleh browser (DOM belum siap), sehingga document.querySelector menghasilkan null.
Solusi: Letakkan tag <script> di akhir body (sebelum </body>) atau bungkus kode Anda dengan event DOMContentLoaded.
3. Event Bubbling yang Tidak Disengaja
Pesan error: (Tidak ada error, tapi logika aplikasi kacau)
Penyebab: Ketika Anda mengklik elemen di dalam elemen lain, kedua event akan terpicu. Misalnya, mengklik tombol “Hapus” di dalam sebuah “Card”, tapi yang terhapus malah “Card”-nya.
Solusi: Gunakan event.stopPropagation() di dalam handler untuk menghentikan event agar tidak naik ke elemen induk.
buttonHapus.addEventListener('click', (e) => {
e.stopPropagation(); // Menghentikan event agar tidak memicu klik pada parent
console.log("Tombol hapus diklik!");
});
Dengan memahami konsep-konsep di atas, Anda kini sudah siap untuk membangun interaksi yang lebih kompleks dan dinamis dalam aplikasi web Anda. Selamat mencoba!