kodingup.camp

Beranda/JavaScript Mastery: Fundamentals

Menangani Input Pengguna

Modul 10 dari 164 menit bacaUser input handling

Isi modul

    Kenapa ini penting

    Program yang hanya mengolah data yang sudah tertulis di kode itu terbatas. Program yang berguna menerima input dari pengguna: nama, umur, jumlah barang, pilihan menu. Di modul ini kamu belajar dua cara mengambil input: lewat browser (prompt dan alert) dan lewat terminal Node.js (readline). Kamu juga belajar fakta penting yang sering menjebak: input dari pengguna hampir selalu berupa string, bahkan ketika pengguna mengetik angka. Kalau tidak dikonversi, "10" + "5" akan menjadi "105", bukan 15.

    Konsep inti

    Input di browser: prompt, alert, confirm

    Browser menyediakan tiga dialog sederhana:

    Function Fungsi Nilai kembalian
    alert(pesan) Menampilkan pesan dengan tombol OK undefined
    prompt(pesan, nilaiAwal) Meminta pengguna mengetik teks String yang diketik, atau null kalau pengguna menekan Cancel
    confirm(pesan) Pertanyaan ya/tidak true (OK) atau false (Cancel)

    Dialog ini bersifat blocking: halaman berhenti sampai pengguna menutupnya. Cocok untuk belajar, tapi aplikasi sungguhan memakai form HTML (dibahas di fase selanjutnya). Ketiganya hanya ada di browser. Jalankan di Console DevTools atau lewat file HTML.

    Input di Node.js: modul readline

    Di terminal, Node.js menyediakan modul bawaan node:readline. Versi modern node:readline/promises memakai await, sehingga kodenya terbaca berurutan dari atas ke bawah:

    1. Buat antarmuka yang membaca dari keyboard (process.stdin) dan menulis ke layar (process.stdout).
    2. Panggil await rl.question("pertanyaan") untuk menunggu jawaban.
    3. Tutup antarmuka dengan rl.close() setelah selesai, supaya program bisa berhenti.

    await artinya "tunggu sampai hasilnya siap". Kamu akan mempelajarinya lebih dalam di materi asynchronous. Untuk sekarang, cukup tahu bahwa await bisa dipakai langsung di tingkat atas file kalau file-nya berupa ES module. Caranya: simpan file dengan ekstensi .mjs, atau tambahkan "type": "module" di package.json.

    Semua input adalah string

    prompt dan rl.question selalu mengembalikan string. Untuk menghitung, ubah dulu ke number:

    Cara "42" "3.5" "12abc" "" " 7 "
    Number(x) 42 3.5 NaN 0 7
    parseInt(x, 10) 42 3 12 NaN 7
    parseFloat(x) 42 3.5 12 NaN 7
    +x (unary plus) 42 3.5 NaN 0 7

    Perhatikan perbedaannya:

    Validasi input

    Jangan pernah percaya input begitu saja. Pengguna bisa mengosongkan kolom, mengetik huruf, menekan Cancel, atau memasukkan angka negatif. Pola validasi dasar:

    1. Cek apakah input ada (bukan null dan bukan string kosong setelah trim()).
    2. Konversi ke number.
    3. Cek dengan Number.isNaN(...) atau Number.isFinite(...).
    4. Cek aturan bisnis (misalnya umur antara 0 dan 120).

    Contoh kode

    Versi browser. Tempel di Console DevTools atau masukkan ke script.js yang dihubungkan ke HTML:

    // Hanya jalan di BROWSER
    const nama = prompt("Siapa namamu?", "Tamu");
    
    if (nama === null) {
      alert("Kamu menekan Cancel.");
    } else {
      const teksUmur = prompt(`Halo ${nama}! Berapa umurmu?`);
      const umur = Number(teksUmur);
    
      if (teksUmur === null || teksUmur.trim() === "" || Number.isNaN(umur)) {
        alert("Umur harus berupa angka.");
      } else {
        alert(`${nama}, tahun depan kamu berumur ${umur + 1} tahun.`);
      }
    }
    
    const lanjut = confirm("Mau lanjut belajar?");
    console.log(lanjut); // → true atau false
    

    Versi Node.js. Simpan sebagai kalkulator.mjs, jalankan dengan node kalkulator.mjs:

    // kalkulator.mjs, input dari terminal
    import * as readline from "node:readline/promises";
    import { stdin as input, stdout as output } from "node:process";
    
    const rl = readline.createInterface({ input, output });
    
    const teksA = await rl.question("Angka pertama: ");
    const teksB = await rl.question("Angka kedua: ");
    rl.close();
    
    // Tanpa konversi: string digabung
    console.log("Tanpa konversi:", teksA + teksB);
    // → (input 10 dan 5) Tanpa konversi: 105
    
    // Dengan konversi
    const a = Number(teksA.replace(",", "."));
    const b = Number(teksB.replace(",", "."));
    
    if (Number.isNaN(a) || Number.isNaN(b) || teksA.trim() === "" || teksB.trim() === "") {
      console.log("Input harus berupa angka.");
    } else {
      console.log("Hasil penjumlahan:", a + b);
      // → (input 10 dan 5) Hasil penjumlahan: 15
    }
    

    Perbandingan cara konversi yang bisa langsung kamu jalankan:

    const contoh = ["42", "3.5", "12abc", "", "  7  ", "3,5"];
    for (const x of contoh) {
      console.log(JSON.stringify(x), Number(x), parseInt(x, 10), parseFloat(x));
    }
    // → "42" 42 42 42
    // → "3.5" 3.5 3 3.5
    // → "12abc" NaN 12 12
    // → "" 0 NaN NaN
    // → "  7  " 7 7 7
    // → "3,5" NaN 3 3
    

    Kesalahan umum

    1. Lupa mengonversi input ke number. prompt("Angka?") + 1 dengan input 5 menghasilkan "51". Selalu konversi dengan Number() atau parseFloat().
    2. Tidak menangani Cancel. prompt mengembalikan null saat Cancel, dan null.trim() akan error. Cek null dulu.
    3. Menganggap string kosong sebagai angka valid. Number("") bernilai 0. Cek teks.trim() === "" sebelum konversi.
    4. Lupa rl.close() di Node.js. Program tidak mau berhenti karena masih menunggu input. Tutup readline setelah selesai.
    5. Memakai await di file .js biasa (CommonJS). Muncul error tentang await. Gunakan ekstensi .mjs atau tambahkan "type": "module" di package.json.

    Latihan

    1. Mudah, (Browser) Minta nama pengguna dengan prompt, lalu tampilkan "Selamat datang, <nama>!" dengan alert. Kalau Cancel, tampilkan "Sampai jumpa".
    2. Sedang, (Node.js) Minta panjang dan lebar persegi panjang dari terminal, lalu tampilkan luasnya. Terima juga input dengan koma seperti 2,5.
    3. Menantang, (Node.js) Buat function bacaAngka(teks) yang mengembalikan number valid atau null kalau input tidak valid (kosong, bukan angka, atau ada sisa huruf seperti "12abc"). Uji dengan array input tanpa readline.
    Lihat solusi

    1.

    const nama = prompt("Nama kamu?");
    if (nama === null || nama.trim() === "") {
      alert("Sampai jumpa");
    } else {
      alert(`Selamat datang, ${nama.trim()}!`);
    }
    

    2.

    // luas.mjs
    import * as readline from "node:readline/promises";
    import { stdin as input, stdout as output } from "node:process";
    
    const rl = readline.createInterface({ input, output });
    const p = Number((await rl.question("Panjang: ")).replace(",", "."));
    const l = Number((await rl.question("Lebar: ")).replace(",", "."));
    rl.close();
    
    if (Number.isNaN(p) || Number.isNaN(l)) {
      console.log("Input tidak valid");
    } else {
      console.log("Luas:", p * l);
    }
    // → (input 2,5 dan 4) Luas: 10
    

    3.

    function bacaAngka(teks) {
      if (teks === null || teks.trim() === "") return null;
      const angka = Number(teks.trim().replace(",", "."));
      return Number.isFinite(angka) ? angka : null;
    }
    
    const uji = ["42", " 3,5 ", "", "12abc", "abc", "-7"];
    for (const t of uji) {
      console.log(JSON.stringify(t), "→", bacaAngka(t));
    }
    // → "42" → 42
    // → " 3,5 " → 3.5
    // → "" → null
    // → "12abc" → null
    // → "abc" → null
    // → "-7" → -7
    

    Ringkasan

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.