Formlar, bir uygulamanın kullanıcısıyla kurduğu en eski sözleşmedir. Yine de çoğu proje hâlâ kullanıcının yarım saat doldurduğu formu tek bir doğrulama hatasında buharlaştıran akışlar barındırıyor. İyi bir form üç katmandan oluşur: doğru doğrulama, kaybolan taslak ve zarafetle verilen hata mesajı.

Doğrulama: Hem Tarayıcıda Hem Sunucuda

HTML'in yerleşik doğrulaması (required, pattern, type) ilk savunma hattıdır; ama tek başına yetmez, çünkü sunucu tarafındaki denetim olmazsa kötü niyetli istek kapıyı zaten bulur. İstemci tarafında UX için canlı doğrulama, sunucuda ise tek gerçeklik kaynağı:

form.addEventListener("submit", (olay) => {
  if (!form.checkValidity()) {
    olay.preventDefault();
    const ilkHatali = form.querySelector(":invalid");
    ilkHatali?.focus();
    ilkHatali?.reportValidity();
    return;
  }
  buton.disabled = true; // çift gönderimi engelle
});

Kullanıcıyı cezalandırmayın: hata mesajını alanın hemen yanında, ne yapması gerektiğini söyleyerek verin. "Geçersiz giriş" değil, "Telefon numarası 0 olmadan 10 haneli olmalı" demek, farkı yaratır. Doğrulama zamanlaması da önemlidir: alanı terk ederken uyar, yazarken düzeltmeyi teklif et; daha yazma biterken kırmızıyla bağırmak yalnızca gerginlik üretir. Kısıtları nerede tutacağınız da kritik bir mimari karardır: kural setini tek bir modülde toplayıp istemci ve sunucuda aynı şemayı paylaşmak, çift bakımın getirdiği sürüş hatasını kökten önler.

Taslak kaydını kullanıcıya bırakmayın: yazma durduğunda otomatik kaydedin, her tuşta kaydetmeye çalışıp performans harcamayın. Beş yüz milisaniyelik bir bekleme (debounce) hem depolamayı korur hem de yazma akışını bölmez.

Taslak Kurtarma

En sık konuşulan ama en çok atlanan özellik: kullanıcının yazdığını otomatik kaydetmek. input olayında localStorage'a yazmak, sayfa geri döndüğünde geri yüklemek yeterlidir:

const anahtar = "taslak:yorum";
input.addEventListener("input", () => {
  localStorage.setItem(anahtar, input.value);
});
window.addEventListener("load", () => {
  const taslak = localStorage.getItem(anahtar);
  if (taslak) input.value = taslak;
});
form.addEventListener("submit", () => localStorage.removeItem(anahtar));

Taslağı yüklerken kullanıcıya haber verin: "Yarım kalan yorumunuz geri yüklendi" ibaresi ve bir "temizle" bağlantısı, geri yükleme özelliğinin gizli bir sürpriz değil, bilinçli bir nezaket olduğunu gösterir. Uzun formlarda adım adım kayıt daha da değerlidir; çok adımlı bir başvuru akışında her adımın tamamlanan bölümünü ayrı anahtarlarla saklamak, kullanıcının dört ekran sonra kaybettiği veriyi kurtarır. Depolama kotası doluysa sessizce başarısız olmak da bir seçenek değildir; try/catch ile yazma hatasını yakalayıp kullanıcıyı veri olmadan bırakmamak, bu küçük mekanizmanın kendi hata planıdır.

Hata Bir Son Değil

Gönderim başarısız olduğunda kullanıcının verisi kaybolmasın; girileni tutup sunucu dönünce forma geri yerleştirin. Ağ kesilirse taslağı saklayıp tekrar deneme butonunu görünür kılın. Sunucu tarafındaki doğrulama hatasını da alanlara eşleyip ilgili inputun altına yerleştirin; kullanıcı hataların özetini değil, kendi düzeltebileceği somut satırları görsün.

İyi form tasarımı aslında affedicilik işidir: kullanıcının her kazara kapanan sekmesi, her kopan ağ bağlantısı ve her yanlış tuşlaması için bir planınız olsun. Doğrulama hataları erken ve net verildiğinde, taslak her durumda güvenceye alındığında ve hata mesajları birer talimat olarak yazıldığında form artık bir engel değil, akışın en pürüzsüz parçası olur.