JavaScript

Belum masuk. Progresmu tidak tersimpan.

Masuk
  • Bab 6 dari 12
  • 30 menit
  • 1 latihan kode
  • 4 soal kuis

DOM dan Event

Di bab ini (8 bagian)
  1. Tujuan
  2. Apa itu DOM?
  3. Memilih elemen
  4. Mengubah elemen
  5. Membuat elemen baru
  6. Event: bereaksi terhadap pengguna
  7. Kesalahan umum
  8. Rangkuman

Tujuan bab ini

  • Memahami apa itu DOM dan kenapa JavaScript bisa mengubah halaman web.
  • Memilih elemen dengan querySelector dan querySelectorAll, lalu mengubah teks, class, dan style-nya.
  • Membuat elemen baru dan menambahkannya ke halaman.
  • Menangani event click, input, dan submit dengan addEventListener, termasuk event object, preventDefault, dan event delegation.

Apa itu DOM?

Saat browser membuka file HTML, ia tidak menyimpan HTML itu sebagai teks. Browser mengubahnya menjadi pohon objek bernama DOM (Document Object Model). Setiap tag menjadi sebuah node yang punya induk, anak, dan saudara, mirip silsilah keluarga.

<body>
  <h1>Toko Kita</h1>
  <ul>
    <li>Kaos</li>
    <li>Topi</li>
  </ul>
</body>

Di pohonnya, body adalah induk dari h1 dan ul, lalu ul adalah induk dari dua li. Pintu masuk ke pohon ini adalah objek global document. Lewat document, JavaScript bisa membaca elemen, mengubah isinya, atau menambah elemen baru, dan browser langsung menggambar ulang halaman.

Penting: document dan window hanya ada di browser. Kalau kamu menjalankan kode DOM dengan Node.js di terminal, hasilnya ReferenceError: document is not defined.

Memilih elemen dan menangani event

Memilih elemen

Dua method ini menerima selector CSS, jadi apa yang kamu tulis di CSS juga berlaku di sini.

const judul = document.querySelector("h1");        // elemen pertama yang cocok
const tombol = document.querySelector("#beli");    // berdasarkan id
const kartu = document.querySelector(".kartu");    // berdasarkan class
const semuaItem = document.querySelectorAll("li"); // semua yang cocok

console.log(semuaItem.length); // 2
semuaItem.forEach(li => console.log(li.textContent));
// Kaos
// Topi
  • querySelector mengembalikan elemen pertama yang cocok, atau null kalau tidak ada.
  • querySelectorAll mengembalikan NodeList berisi semua elemen yang cocok. NodeList bisa di-forEach, tapi bukan array asli; pakai Array.from(...) kalau butuh map atau filter.

Mengubah elemen

Setelah elemennya didapat, kamu bisa mengubah banyak hal:

judul.textContent = "Toko Kita Diskon!";      // ganti teks
kartu.innerHTML = "<strong>Baru</strong>";     // ganti isi sebagai HTML
kartu.classList.add("aktif");                  // tambah class
kartu.classList.remove("tersembunyi");         // hapus class
kartu.classList.toggle("dipilih");             // tambah kalau belum ada, hapus kalau sudah
console.log(kartu.classList.contains("aktif")); // true
judul.style.color = "green";                   // ubah style langsung
judul.style.fontSize = "32px";                 // nama CSS jadi camelCase
PropertiIsinyaKapan dipakai
textContentTeks murniMenampilkan data, terutama dari input pengguna
innerHTMLTeks yang dibaca sebagai HTMLMenyusun potongan HTML milikmu sendiri
classListDaftar classMengganti tampilan lewat CSS
styleStyle inlinePerubahan kecil yang dinamis

Kenapa textContent lebih aman untuk input pengguna? Karena innerHTML menjalankan apa pun sebagai HTML. Kalau seseorang mengetik tag berbahaya, misalnya <img src=x onerror="...">, kodenya bisa ikut jalan. Ini celah keamanan bernama XSS. Untuk mengubah tampilan, classList biasanya lebih rapi daripada style, karena aturan tampilannya tetap tinggal di file CSS.

Membuat elemen baru

const item = document.createElement("li");
item.textContent = "Tas";
item.classList.add("baru");
document.querySelector("ul").appendChild(item);

Langkahnya selalu tiga: buat elemen, isi (teks, class, atribut), lalu pasang ke pohon dengan appendChild atau append. Sebelum dipasang, elemen itu sudah ada di memori tapi belum terlihat di halaman. Untuk menghapus elemen, panggil item.remove().

Event: bereaksi terhadap pengguna

Event adalah sinyal bahwa sesuatu terjadi: tombol diklik, teks diketik, form dikirim. Kamu memasang "pendengar" dengan addEventListener(jenisEvent, callback). Callback ini baru dijalankan saat event terjadi, bukan saat baris itu dibaca.

const tombol = document.querySelector("#beli");
const jumlah = document.querySelector("#jumlah");
let total = 0;

tombol.addEventListener("click", () => {
  total++;
  jumlah.textContent = total;
});

Urutan kejadiannya: saat halaman dimuat, kode di atas hanya mendaftarkan callback, belum ada yang dihitung. Setiap kali pengguna mengklik, browser memanggil callback itu, total bertambah satu, lalu teks di layar diperbarui. Variabel total tetap tersimpan di antara klik karena callback adalah closure yang mengingat variabel di luarnya. Pola "simpan state di variabel, lalu tulis ke DOM" ini adalah dasar dari hampir semua interaksi, dari tombol like sampai keranjang belanja.

Event object

Browser selalu mengirim satu argumen ke callback: event object, biasanya dinamai e atau event. Isinya informasi tentang kejadian itu. Yang paling sering dipakai adalah e.target, yaitu elemen tempat event terjadi.

const kolom = document.querySelector("#nama");
const pratinjau = document.querySelector("#pratinjau");

kolom.addEventListener("input", (e) => {
  pratinjau.textContent = "Halo, " + e.target.value;
});

Event input berjalan setiap kali isi kolom berubah, jadi pratinjau ikut berubah saat kamu mengetik, huruf demi huruf.

submit dan preventDefault

Secara bawaan, form yang dikirim akan memuat ulang halaman. Di aplikasi modern kita biasanya ingin mengolah datanya dengan JavaScript, jadi perilaku bawaan itu dibatalkan dengan e.preventDefault().

const form = document.querySelector("#form-todo");

form.addEventListener("submit", (e) => {
  e.preventDefault(); // halaman tidak reload
  const teks = form.querySelector("input").value.trim();
  if (!teks) return;
  console.log("Tugas baru:", teks);
  form.reset();
});

Pasang listener submit di form, bukan click di tombolnya. Dengan begitu, menekan Enter di kolom input juga ikut tertangani.

Event delegation singkat

Bayangkan daftar tugas yang item-nya terus bertambah. Memasang listener ke setiap li merepotkan, apalagi untuk item yang dibuat belakangan. Karena event "menggelembung" (bubbling) dari elemen anak ke induknya, kamu cukup memasang satu listener di induk:

document.querySelector("#daftar").addEventListener("click", (e) => {
  if (e.target.matches("li")) {
    e.target.classList.toggle("selesai");
  }
});

e.target memberi tahu item mana yang sebenarnya diklik, dan matches memastikan yang diklik memang li. Item baru otomatis ikut tertangani tanpa listener tambahan.

Kesalahan umum

  • Script jalan sebelum HTML siap. querySelector menghasilkan null karena elemennya belum dibuat. Taruh <script> di akhir body atau pakai atribut defer.
  • Memanggil callback saat mendaftarkannya. addEventListener("click", tambah()) menjalankan tambah sekali, lalu mendaftarkan hasilnya. Tulis tambah tanpa kurung.
  • Lupa preventDefault di submit. Halaman reload dan semua data di layar hilang.
  • Memakai innerHTML untuk teks dari pengguna. Pakai textContent supaya aman dari XSS.
  • Menganggap textContent berupa angka. Isinya selalu string; ubah dengan Number(...) sebelum menghitung.

Rangkuman

  • DOM adalah pohon objek dari HTML, diakses lewat document, dan hanya tersedia di browser.
  • querySelector mengambil elemen pertama yang cocok, querySelectorAll mengambil semuanya.
  • Ubah elemen lewat textContent, innerHTML, classList, dan style; buat elemen baru dengan createElement lalu pasang dengan appendChild.
  • addEventListener menjalankan callback saat event terjadi; event object membawa target dan preventDefault.
  • Event delegation memakai bubbling: satu listener di induk menangani semua anak, termasuk yang baru dibuat.

Selesaikan bab ini

  1. 1. Baca materi
  2. 2. Latihan kode (1)
  3. 3. Kuis (4 soal)

Latihan kode: Tombol penghitung

Buat penghitung yang hidup dengan addEventListener:

  • Tombol #tambah menaikkan angka di #hitung sebesar 1.
  • Tombol #kurang menurunkan angka sebesar 1.
  • Tombol #reset mengembalikan angka ke 0.
  • Saat angka di bawah 0, #hitung mendapat class negatif (warnanya merah). Saat angka 0 atau lebih, class itu dilepas.

Simpan angkanya di variabel, lalu tulis ke layar dengan textContent.

Cek pemahaman

  1. 1Apa yang dikembalikan document.querySelector(".kartu") bila tidak ada elemen yang cocok?

  2. 2Kode DOM seperti document.querySelector bisa langsung dijalankan dengan Node.js di terminal.

  3. 3Apa yang ditampilkan kode berikut?

    const p = document.createElement("p");
    p.classList.add("a");
    p.classList.toggle("b");
    p.classList.toggle("a");
    console.log(p.className);
  4. 4Untuk apa e.preventDefault() dipanggil di dalam listener submit?