JavaScript Form Validation (Form Doğrulama)

Form doğrulama (validation) kullanıcıdan gelen verinin eksiksiz ve geçerli olmasını sağlar. Genellikle iki katmanlı yapılır: 1) Anlık kontrol (input/blur) + 2) Gönderimde son kontrol (submit).

Altın kural
JavaScript doğrulama kullanıcı deneyimi içindir. Güvenlik için her zaman sunucu tarafında da doğrulama yapılmalıdır.

1) Örnek Form (Ad, E-posta, Şifre, KVKK)

<form id="frmValid" novalidate>

  <div class="mb-3">
    <label class="form-label">Ad Soyad</label>
    <input id="adsoyad" name="adsoyad" type="text" class="form-control" placeholder="Ad Soyad">
    <div class="small text-danger mt-1" id="err_adsoyad"></div>
  </div>

  <div class="mb-3">
    <label class="form-label">E-posta</label>
    <input id="email" name="email" type="email" class="form-control" placeholder="ornek@mail.com">
    <div class="small text-danger mt-1" id="err_email"></div>
  </div>

  <div class="mb-3">
    <label class="form-label">Şifre</label>
    <input id="sifre" name="sifre" type="password" class="form-control" placeholder="En az 8 karakter">
    <div class="small text-danger mt-1" id="err_sifre"></div>
  </div>

  <div class="form-check mb-3">
    <input class="form-check-input" type="checkbox" id="kvkk" name="kvkk">
    <label class="form-check-label" for="kvkk">KVKK metnini okudum, kabul ediyorum</label>
    <div class="small text-danger mt-1" id="err_kvkk"></div>
  </div>

  <button id="btnGonder" class="btn btn-primary" type="submit">Gönder</button>
  <span id="loading" class="ms-2 small text-muted" style="display:none;">Gönderiliyor...</span>

  <div id="result" class="mt-3"></div>

</form>
Neden novalidate?
Tarayıcının kendi doğrulama baloncuklarını kapatır; böylece tüm kontrol ve mesajları bizim UI standardımızla gösterebiliriz.

2) JavaScript Doğrulama Kodu (input + blur + submit)

(() => {

  // --- Helpers ---
  const $ = (id) => document.getElementById(id);

  const setError = (field, message) => {
    const err = $("err_" + field);
    if (err) err.textContent = message || "";
  };

  const clearAllErrors = () => {
    ["adsoyad","email","sifre","kvkk"].forEach(f => setError(f, ""));
  };

  const isEmail = (val) => {
    // Basit ve yeterli email kontrolü (aşırı katı regexlerden kaçın)
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val);
  };

  // --- Form elements ---
  const frm   = $("frmValid");
  const btn   = $("btnGonder");
  const load  = $("loading");
  const res   = $("result");

  const inpAd    = $("adsoyad");
  const inpEmail = $("email");
  const inpSifre = $("sifre");
  const inpKvkk  = $("kvkk");

  // --- Field validations ---
  const validateAd = () => {
    const v = inpAd.value.trim();
    if (!v) return setError("adsoyad", "Ad Soyad boş olamaz."), false;
    if (v.length < 3) return setError("adsoyad", "En az 3 karakter giriniz."), false;
    setError("adsoyad", "");
    return true;
  };

  const validateEmail = () => {
    const v = inpEmail.value.trim();
    if (!v) return setError("email", "E-posta boş olamaz."), false;
    if (!isEmail(v)) return setError("email", "Geçerli bir e-posta giriniz."), false;
    setError("email", "");
    return true;
  };

  const validateSifre = () => {
    const v = inpSifre.value;
    if (!v) return setError("sifre", "Şifre boş olamaz."), false;
    if (v.length < 8) return setError("sifre", "Şifre en az 8 karakter olmalı."), false;

    // İsteğe bağlı: güç kontrolü (en az 1 harf + 1 rakam)
    const hasLetter = /[A-Za-zÇĞİÖŞÜçğıöşü]/.test(v);
    const hasNumber = /\d/.test(v);
    if (!hasLetter || !hasNumber) {
      return setError("sifre", "Şifre en az 1 harf ve 1 rakam içermeli."), false;
    }

    setError("sifre", "");
    return true;
  };

  const validateKvkk = () => {
    if (!inpKvkk.checked) return setError("kvkk", "Devam etmek için KVKK onayı gerekli."), false;
    setError("kvkk", "");
    return true;
  };

  const validateAll = () => {
    // Sıralı doğrulama: kullanıcıya daha anlaşılır geri bildirim
    const ok1 = validateAd();
    const ok2 = validateEmail();
    const ok3 = validateSifre();
    const ok4 = validateKvkk();
    return ok1 && ok2 && ok3 && ok4;
  };

  // --- Live validation events ---
  inpAd.addEventListener("blur", validateAd);
  inpEmail.addEventListener("blur", validateEmail);
  inpSifre.addEventListener("blur", validateSifre);
  inpKvkk.addEventListener("change", validateKvkk);

  // İstersen anlık (input) doğrulama da ekleyebilirsin:
  // inpEmail.addEventListener("input", () => { if (inpEmail.value.trim()) validateEmail(); });

  // --- Submit handler ---
  frm.addEventListener("submit", async (e) => {
    e.preventDefault();
    res.innerHTML = "";

    clearAllErrors();

    const ok = validateAll();
    if (!ok) {
      res.innerHTML = '<div class="alert alert-danger border">Lütfen hataları düzeltip tekrar deneyin.</div>';
      return;
    }

    // Loading state (örnek)
    btn.disabled = true;
    load.style.display = "inline";

    try {
      // Simülasyon (gerçekte fetch/AJAX ile gönderirsin)
      await new Promise(r => setTimeout(r, 900));

      // FormData örneği
      const fd = new FormData(frm);
      const payload = Object.fromEntries(fd.entries());

      res.innerHTML =
        '<div class="alert alert-success border">' +
        '<div class="fw-semibold">Başarılı ✅</div>' +
        '<div class="small text-muted mt-1">Form doğrulandı. (Demo) Konsolu kontrol et.</div>' +
        '</div>';

      console.log("Gönderilecek payload:", payload);

      // İstersen formu temizle:
      // frm.reset();

    } catch (err) {
      res.innerHTML = '<div class="alert alert-danger border">Bir hata oluştu. Lütfen tekrar deneyin.</div>';
      console.error(err);
    } finally {
      btn.disabled = false;
      load.style.display = "none";
    }
  });

})();

3) İnce İpuçları ve Püf Noktalar

  • Tek mesaj alanı: Her input altına err_... div’i koymak, UI’yi standartlaştırır.
  • Blur + Submit: Blur ile “erken uyarı”, submit ile “son kontrol” en iyi kombinasyon.
  • Regex’i abartma: E-posta gibi alanlarda aşırı katı regex kullanıcıyı gereksiz zorlar.
  • Disable + Loading: Çift tıklayıp iki kez gönderme sorununu engellersin.
  • Sunucu doğrulaması şart: JS devre dışı olabilir; güvenlik sunucuda sağlanır.
  • HTML5 input type: type="email" / type="number" mobil klavyeyi de iyileştirir.