proyekdomtugasMenengah4 mnt baca

Proyek Mini: Todo List

Proyek capstone DOM: bangun aplikasi todo lengkap dari nol. Menggabungkan seleksi elemen, event, delegation, classList, dan localStorage dalam satu aplikasi nyata dengan arsitektur render-ulang dari single source of truth.

Proyek Capstone: Kenapa Todo List?

Todo list terlihat sederhana, tapi ia memaksa memakai SEMUA yang kamu pelajari di modul DOM: seleksi elemen, membuat elemen, event listener, delegation, classList, traversal, dan localStorage. Aplikasi produksi, dari kasir sampai dashboard admin, pada dasarnya adalah pola yang sama: data di memori, tampilkan ke layar, tangkap aksi user, simpan perubahan. Kuasai pola ini sekali, dan kamu bisa membangun aplikasi CRUD apa pun.

Arsitektur: Satu Sumber Kebenaran

Aturan emas proyek ini: array todos di memori adalah SATU-SATUNYA sumber kebenaran. DOM hanyalah cermin: setiap ada perubahan, render ulang list dari array. Jangan pernah membaca state dari DOM (mis. menghitung li yang punya class selesai), karena DOM dan data bisa tidak sinkron dan bug-nya sulit dilacak.

javascript
// Struktur data: tiap todo punya id unik, teks, dan status
let todos = baca("todos", []);

function simpanSemua() {
  simpan("todos", todos);
}

function render() {
  const ul = document.getElementById("daftar");
  ul.innerHTML = ""; // kosongkan, lalu bangun ulang dari data
  todos.forEach(todo => {
    const li = document.createElement("li");
    li.dataset.id = todo.id;
    li.classList.toggle("selesai", todo.selesai);

    const label = document.createElement("span");
    label.textContent = todo.teks;

    const btnHapus = document.createElement("button");
    btnHapus.textContent = "Hapus";
    btnHapus.className = "hapus";

    li.append(label, btnHapus);
    ul.appendChild(li);
  });

  const sisa = todos.filter(t => !t.selesai).length;
  document.getElementById("info").textContent =
    sisa === 0 ? "Semua selesai!" : sisa + " tersisa";
}

dataset.id menyimpan id di atribut data-id, cara standar menautkan elemen DOM ke data tanpa variabel global berantakan.

Aksi: Tambah, Toggle, Hapus

Tiga fungsi murni mengubah data, lalu simpan dan render ulang. Perhatikan polanya selalu sama: ubah array, simpan, render.

javascript
function tambah(teks) {
  const bersih = teks.trim();
  if (!bersih) return;
  todos.push({ id: Date.now(), teks: bersih, selesai: false });
  simpanSemua();
  render();
}

function toggle(id) {
  const todo = todos.find(t => t.id === id);
  if (todo) {
    todo.selesai = !todo.selesai;
    simpanSemua();
    render();
  }
}

function hapus(id) {
  todos = todos.filter(t => t.id !== id);
  simpanSemua();
  render();
}

Event: Delegation untuk List Dinamis

Item dibuat setelah halaman dimuat, jadi delegation wajib (modul event delegation). Satu listener di <ul> menangani klik label (toggle) dan tombol hapus:

javascript
document.getElementById("daftar").addEventListener("click", (e) => {
  const li = e.target.closest("li");
  if (!li) return;
  const id = Number(li.dataset.id);

  if (e.target.closest(".hapus")) {
    hapus(id);
  } else {
    toggle(id);
  }
});

document.getElementById("form").addEventListener("submit", (e) => {
  e.preventDefault();
  const input = document.getElementById("input-todo");
  tambah(input.value);
  input.value = "";
  input.focus(); // UX bagus: siap ketik tugas berikutnya
});

Fungsi baca dan simpan memakai pola aman dari modul localStorage (try-catch + fallback + JSON).

Fitur Wajib dan Kriteria

  1. Input + tombol "Tambah": tugas baru muncul di list, input dikosongkan dan difokuskan lagi.
  2. Klik tugas: toggle selesai (class selesai + coret via CSS text-decoration: line-through).
  3. Tombol hapus per tugas, memakai event delegation.
  4. Data tersimpan di localStorage: refresh halaman tidak menghilangkan tugas.
  5. Penghitung sisa: "3 tersisa" atau "Semua selesai!".

Tulis HTML+JS dari nol di editor tugas di bawah, lalu minta penilaian AI. Tidak ada playground jadi: kerjakan mandiri, ini simulasi kerja nyata.

Jebakan Umum Proyek Ini

  • Membaca state dari DOM alih-alih dari array todos. Begitu render ulang, semua info hilang.
  • Id duplikat: pakai Date.now() atau counter naik, jangan pakai index array (berubah saat item dihapus).
  • Lupa memanggil simpanSemua() di salah satu aksi: data hilang saat refresh dan bug-nya hanya muncul belakangan.
  • Memasang listener per-li hasil render: setelah render ulang, listener lama ikut terhapus bersama elemennya. Delegation menyelesaikan ini permanen.

Ringkasan

Todo list mengajarkan arsitektur aplikasi front-end sejati: single source of truth di memori, DOM sebagai cermin yang di-render ulang, aksi sebagai fungsi kecil (tambah/toggle/hapus), event delegation untuk konten dinamis, dan localStorage untuk persistensi. Pola persis ini dipakai aplikasi CRUD di dunia kerja, hanya datanya yang diganti.

Tantangan

Pemanasan: Render List

Pemanasan: diberi array todos. Tulis fungsi render() yang mengosongkan #daftar lalu mengisi li per todo (pakai textContent). Fungsi render-ulang-dari-data adalah inti arsitektur proyek ini dan pola standar aplikasi CRUD profesional: setiap perubahan data selalu diikuti render ulang agar tampilan tidak pernah basi.

<!doctype html>
<html>
<head>
<meta charset="utf-8" />

</head>
<body>
<h1>Halo JS</h1>
<p>Buka console preview untuk melihat output.</p>
<script src="index.js"></script>
</body>
</html>

Tugas

Aplikasi Todo List

Bangun aplikasi todo lengkap: tambah tugas, toggle selesai, hapus per item (delegation), simpan ke localStorage, tampilkan sisa tugas. Tulis HTML+JS dari nol di editor bawah.

Kriteria penilaian:

  • Semua 5 fitur wajib berfungsi
  • Menggunakan event delegation untuk hapus/toggle
  • Data bertahan setelah refresh (localStorage + JSON)
  • Kode terstruktur (fungsi render/tambah/hapus terpisah)

AI tutor akan memeriksa bug, kesalahan syntax, dan memberi saran perbaikan.