HTML form doğrulamasının yetersiz kullanımı
(expressionstatement.com)- HTML formları
required,type="email",pattern,maxlength,setCustomValiditygibi yerel doğrulama özelliklerine zaten sahip, ancak pratikte kullanım düzeyi bu özelliklerin kapsamına kıyasla düşük kalıyor - En güçlü seçenek olan
setCustomValidity, keyfi doğrulama mantığını ve karmaşık durumları ele alabiliyor; ancak yalnızca bir DOM metodu olarak sunulduğu için deklaratif bileşenlerle iyi uyuşmuyor - React gibi ortamlarda başlangıç değeri doğrulamasını doğru yapmak için
useRef,useLayoutEffect,onChangebirbirine dolaşıyor ve aynı doğrulama mantığı başlangıç render’ı ile değişiklik işleyicisinde kolayca yineleniyor custom-validitygibi öznitelik tabanlı bir soyutlama olsaydı, eşzamansız kullanıcı adı çakışma kontrolü veya parola doğrulama gibi durum ve girdi arasında bağımlılık olan doğrulamaları tek yerde ifade etmek mümkün olurdu- Yerel form doğrulamasının düşük benimsenmesi, özellik eksikliğinden çok API kullanılabilirliği sorununa daha yakın; deklaratif bir API HTML spesifikasyonuna girerse kullanım alanı büyüyebilir
HTML form doğrulamasının zaten sundukları
- Boş girişi engellemenin en basit yolu
requiredözniteliğini eklemektir - Girdi kısıtları genel olarak üç şekilde uygulanabilir
type="email",type="number",type="url"gibi girdi tiplerini kullanmakpattern,maxlengthgibi kısıt özniteliklerini kullanmak- Girdinin
setCustomValidityDOM metodunu kullanmak
setCustomValidity, keyfi doğrulama mantığını ve karmaşık senaryoları ele alabildiği için en güçlü araçtır- İlk iki yaklaşım HTML öznitelikleriyle deklaratif biçimde tanımlanabilirken,
setCustomValidityiçin bir metot çağrısı gerekir - DOM öznitelikleri ve property’leri arasındaki farkı ele alan başvuru olarak Attributes vs Properties bağlantısı veriliyor
setCustomValidity'nin rahatsız edici hale geldiği nokta
setCustomValidity, karşılık gelen bir HTML özniteliği olmadan yalnızca bir metot olarak sunuluyor- Bir string verildiğinde girdi invalid duruma geçiyor ve tarayıcı bu string’i doğrulama hatasının nedeni olarak gösteriyor
- Boş string verildiğinde ise başka bir kısıt yoksa girdi valid duruma dönüyor
requiredbenzeri davranışı elle uygulamak için değer her değiştiğindesetCustomValidityçağrılmalı- Ancak girdi başlangıçta valid durumda olduğu için, bileşen resetlendikten hemen sonra submit düğmesine basılırsa form gönderimi geçebilir
- Bunun nedeni, değer boş olsa bile değişiklik olayı oluşmadan doğrulama kodunun çalışmamasıdır
- Başlangıç değerini de doğru ele almak için aynı doğrulamanın bileşen mount edildiğinde de çalıştırılması gerekir
Deklaratif bileşenlerde artan boilerplate
- Başlangıç değeri doğrulamasını da kapsayınca kod hızla tekrarlı ve kullanışsız hale geliyor
- Özellikle üç sorun ortaya çıkıyor
- Doğrulama mantığı
onChangeişleyicisiyle başlangıç render aşamasında yineleniyor - İlk doğrulama kodu girdi öğesinden uzak kaldığı için bütünlük azalıyor ve yalnızca bir tarafın değiştirilmesi riski doğuyor
useRef,useLayoutEffect,onChangekombinasyonu girdi sayısı arttıkça aşırı hale geliyor; yalnızca bazı girdilercustomValiditykullandığında daha da kafa karıştırıcı oluyor
- Doğrulama mantığı
- Bu karmaşıklık, tamamen imperatif API’lerin deklaratif bileşenlerde ele alınmasında özellikle belirginleşiyor
CustomValidityiçin, yerel doğrulama özniteliklerinde olduğu gibi değeri deklaratif olarak ayarlayacak bir girdi özniteliği yok- Bir API zahmetliyse, özellik güçlü olsa bile benimsenmesi düşük kalabiliyor; yerel form doğrulamasının yetersiz kullanılmasının ana nedeni de bu
Eksik parça: custom-validity özniteliği
- Gereken şey, doğrudan girdiye atanabilen
custom-validitybenzeri bir deklaratif öznitelik - Deklaratif framework’lerde bu öznitelik, doğrulama durumunu girdi öğesine yakın tutmayı sağlar
- Şu anda
HTML Speciçinde gerçek bircustom-validityyok - Demo amacıyla, kullanıcı alanında yapılan bir uygulamayla bu davranış taklit edilebiliyor
- Prodüksiyon için bileşen örneği olarak daha tamamlanmış bir implementasyon sunuluyor
Eşzamansız doğrulama ve girdiler arası bağımlılık
- Gerçek uygulamalardaki doğrulama, yerel kontrollerden daha karmaşık olabilir
- Kullanıcı adı girdisinde, adın zaten kullanımda olup olmadığını sunucuda doğrulamak gerekir; istek sürerken form valid durumda olmamalıdır
- Örnek, boş girdiyi engellemek için
requiredkullanıyor ve yüklenme durumu ile yanıt sonucuna görecustomValidityüzerinden girdiyi invalid duruma getiriyor - Uygulama iki bölümden oluşuyor
- Kullanıcı adı benzersizliği kontrolü isteğinin durumunu
react-queryiçindekiuseQueryile yönetmek customValidityprop’u alabilen özel bir<Input />bileşeni kullanmak
- Kullanıcı adı benzersizliği kontrolü isteğinin durumunu
- Bu yaklaşım, loading, error ve success durumları dahil tüm eşzamansız doğrulama akışını tek bir öznitelikte ifade etmeyi sağlıyor
- Ek örnek olarak, girilen parolanın yeniden girilmesini isteyen bir form veriliyor; burada birbirine bağımlı girdi alanlarının doğrulaması ele alınıyor
Sonuç
setCustomValidity, çeşitli doğrulama ihtiyaçlarını karşılayabilen güçlü bir araçtır- Gerçek kullanım düzeyini belirleyen şey yalnızca özelliğin varlığı değil, o özelliği kullanmayı kolaylaştıran API’dir
custom-validitygibi deklaratif soyutlamalar, yerel form doğrulamasını daha doğal biçimde kullanmayı mümkün kılar- Böyle bir özelliğin bir gün HTML spesifikasyonuna yerel olarak girmesi umulabilir
1 yorum
Hacker News yorumları
Son kontrol ettiğimde, günümüz web tarayıcıları yerleşik HTML doğrulama mesajlarının görünümünü hâlâ biçimlendirmeye izin vermiyordu https://stackoverflow.com/questions/5328883/how-do-i-style-t...
Chrome ve Firefox en azından işletim sistemi platformunun arayüz yönergelerini izleyip
title=""tooltip'leri gibi sistem tarafından gösterilmiş gibi görünselerdi daha az sorun olurdu; ama Chrome sarı/turuncu bir ikon, beyaz zemin üzerinde siyah yazı ve sabit yuvarlatılmış köşeli bir balon kullanıyor; bu da mevcut projenin estetiğiyle ciddi biçimde çatışıyor.Eski Chrome, satıcı önekli sözde öğe seçicilerle doğrulama mesajlarını biçimlendirmeye izin veriyordu; fakat bu özelliği kaldırdıktan sonra geri getirmedi. Bu da “bana yerel bir HTML combobox verin”, “neden hâlâ checkbox listesi yerine kullanması zor Ctrl+tıklama kutusu var” gibi keyfî sinir bozucu şeyler listesine ekleniyor.
validitydurumunu okuyup istediğiniz gibi render etmenin oldukça kolay olması.Asıl sorun, bu geçerlilik durumu değişimlerine doğru şekilde abone olmanın zor olması. Geçerlilik olayları var, ama her zaman tetiklenmiyorlar.
form.reset()çağrısı ya dainput.value = '...'gibi form durumunu programatik olarak değiştirmek bu olayları tetiklemiyor.Bence bu, ayrıca araştırılıp web platformuna önerilebilecek iyi bir konu.
En büyük, uygulaması kolay olmasına rağmen az kullanılan şey,
email,number,urlgibi belirlitypeöznitelik değerlerini kullanmak.Mobilde en uygun klavyeyi açarak kullanıcı deneyimini büyük ölçüde iyileştirebilir.
type=numberkullanmaktan kaçınıp onun yerinetype=text inputmode=numerickullanıyorum. Çoğu kullanıcının sayı girişi için ihtiyaç duymadığı ok düğmeleri eklenmiyor ve iOS’ta klavye de daha iyi oluyor.typedeğerini ayarlamayan şaşırtıcı derecede çok yer var.dategirdilerinde de bunu çok sık gördüm. Her frontend kütüphanesinin kendi tarih widget'ı var ve küçük ekranlarda berbat görünenlerin sayısı da çok.Sırf o widget yüzünden JS ve CSS eklemeniz gerekiyor; bazıları jQuery’ye bağımlı. Elbette çok fazla ayarı olanlar da var, ama çok küçük bir maliyetle her yerde fena durmayan, yerel gibi görünen, çoğu gereksinimi karşılayan ve güncelleme ya da CDN derdi olmadan unutup gidebileceğiniz bir widget elde edebilirsiniz.
Normal girdilerle bile zar zor mümkünken, özel girdiler daha da az olayı destekliyor.
Ürünüm, yerel HTML form doğrulaması kullandığı için erişilebilirlik denetiminden geçemedi; resmi öneri, kendi doğrulama katmanımızı uygulamamız yönündeydi. Ben de bu öneriye katılıyorum.
Yerel HTML doğrulamasında pek çok kusur var ve açıkçası görsel özelleştirme en büyük endişe bile değil. Yine de tabuta çakılan son çiviye yakın.
Örneğin alan başına birden fazla hatayı aynı anda göstermek istiyorsanız, dizeleri birbirine eklemekten başka yol yok. “Sayı gerekli. Sembol gerekli. 10 karakterden uzun olmalı” gibi; bu hem kullanıcı deneyimi açısından kötü hem de erişilebilirlik açısından kötü. Çünkü erişilebilirlik ağacında birleştirilmiş dize içinde gezinemiyorsunuz. Bu uygulamaya özgü bir sorun değil, doğrudan spesifikasyonun sorunu. Kullanıcıların doğrulama hatalarıyla köstebek avı oynaması keyifli değil; bu yüzden birden fazla hatayı aynı anda gösterebilmek gerekir.
Tarayıcıya bağımlı olması da kötü. Kontrol edemiyorsunuz ve uygulamaları da genel olarak berbat. Chrome odaklanma sırasında bir açılır pencere gösteriyor; bu bir popup, modal gibi görünüyor ve tüm form hatalarını aynı anda gösteremediği için başlı başına erişilebilir değil. Önemli bilgileri popup içinde göstermeyin demek erişilebilirliğin temelidir; ama tarayıcının gerçek belgeyi kesintiye uğratmadan yapabileceği pek fazla şey yok.
Belirli bir alana ait olmayan, formun tamamına yönelik hatalar için de hâlâ özel doğrulama gerekir. “A ve B alanları birlikte kullanılamaz” gibi hatalar buna örnektir; öyleyse tutarlı bir doğrulama yaklaşımına sahip olmak daha iyidir.
Yerel input tiplerine uymayan özel bir input’unuz varsa, tutarlılık için gizli bir input koymanız gerekir; bu da erişilebilirliği bozar. Bunu düzeltmek, eninde sonunda erişilebilirlik dostu kendi doğrulama sisteminizi yapmak kadar zordur.
customValidityAPI’si imperatif ve kullanması zahmetli. “Bu alan geçersiz” gibi berbat mesajlar istemiyorsanız özel geçerlilik kullanmamak neredeyse bir seçenek değil. Bu yüzden HTML form doğrulaması kötü.Yine de yerel doğrulama mekanizmalarından yararlanmaya değer olduğunu düşünüyorum. Hata mesajları için yerel geçerlilik tooltip’ini kullanmak zorunda değilsiniz;
input.validityiçindekiValidityState’i doğrudan okuyup mesajları istediğiniz biçimde render edebilir ve gerekirse birden fazla hatayı gösterebilirsiniz.Tarayıcılar iyileşebilir ve standartlaştırılmış bir yaklaşım kullanırsanız bu iyileştirmelerden faydalanabilirsiniz. “Popup kullanmazsan erişilebilirlik bozulur” gibi bir sonuca varmak tuhaf geliyor; ama denetimden geçmeniz gerekiyorsa bu yoldan gitmeniz gerekebilir.
Belirli bir alana ait olmayan hataları ele almanın da teknikleri var. Benim projemde, başka bir alana ait olmayan özel hataları render etmek için görünmeyen, salt okunur bir input oluşturan
HiddenValidationInputbileşenini kullanıyoruz. Sadece koşullu olarak render etmek yeterli olduğu için pratikte oldukça kullanışlı.customValidityAPI’sinin imperatif ve zahmetli olduğuna tamamen katılıyorum. Tam da bu kısmı ele alan bir yazı yazdım ve bunun da zamanla iyileşmesini umuyorum.Chrome’un kaba ve erişilebilirliği düşük tasarımı Chrome’un sorunu; bunun için hata raporu göndereceğim.
“Spesifikasyon” derken kastedilen bu mu? https://html.spec.whatwg.org/multipage/dom.html#concept-elem...
Doğrulama mesajlarının nasıl gösterilmesi gerektiğini tanımlayan bir bölüm göremiyorum. Hatta mesajların mutlaka var olması gerektiğine dair bir şey bile yok.
Açık konuşmak gerekirse, böyle spesifikasyonları yazanlar gerçeklikten kopuk ve spesifikasyona döktükleri şeyleri gerçekten kullanmıyor gibiler. Çok basit şeylerde çalışıyor; ama formlar evrilmeye başladığında eninde sonunda her şeyi kendiniz yazmanın daha iyi olduğunu fark ediyorsunuz.
JS kullanmaya başladığınız anda, doğrulama öznitelikleriyle uğraşmaktansa her şeyi kodla yapmak çok daha kolay hale geliyor.
Bir onay kutusunun etiketi varsa, etikete
forözniteliği eklenip etikete tıklayarak onay kutusunu açıp kapatabilmeyi isterim. Kişisel olarak en çok sinirimi bozan şeylerden biri; belki de sadece ben böyleyimdir.input’ulabelile sarmalayınca da çalışır. İnsanların neden ikisini ayrı tutma eğiliminde olduğunu pek bilmiyorum.Ayrıca tarayıcıların bunları neden ayırmaya başladığını da bilmiyorum. Metnin checkbox ve radio’ları içermesi değil, checkbox ve radio’ların metni içermesi gerektiğini düşünüyorum.
React kullanmayan basit bir örnek burada:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectE...
HTML form doğrulaması harika. Ancak çok büyük bir tuzağı var
Android için Firefox’ta çalışmıyor
https://bugzilla.mozilla.org/show_bug.cgi?id=1510450
Kırmızıyla işaretlenen denetimlerin hata mesajını göremeyen %1’den az kullanıcı için standardı görmezden gelmeye değmez. Daha fazla web sitesi bunu kullandıkça Mozilla’nın tarayıcıyı düzeltmesi yönündeki baskı da artacaktır
Bu, Chrome veya Safari’nin standartlaşmadan önce uyguladığı WebMIDI gibi bir API değil; baştan beri HTML5 spesifikasyonunun bir parçası
Özellikle erişilebilirlik yazılımı kullanan kişilerin siteyi düzgün kullanabilmesi için ne kadar az zaman ayrıldığını düşününce bu daha da doğru. UC Browser’dan da bahsetmeye hazır değilseniz, bu tür bir meselede anılmaya pek değmediğini düşünüyorum
Yine de diğer eklentilerle birlikte uBlock Origin kullanabilmek güçlü bir avantaj
[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1884282
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1897707
Doğrulama hiç uygulanmamış olsaydı belki daha iyi olurdu; bu gerçekten berbat. Birkaç yıl önce uzun ve acılı bir hata ayıklama sürecinden sonra öğrendim ve benimle aynı şeyi yaşayan ilk ya da son kişi olmadığımından eminim
Arama yapana kadar neyi kaçırdığımı hayal bile edemedim ve oldukça şaşırdım. Kendi doğrulamanızı yapmak sorun değil ama bunun çalışması gerekiyor
Aşırı kullanmamaya dikkat etmek gerek
Yakın zamanda Groupon’dan iade almaya çalıştım. Çünkü Groupon’u satın aldığım işletme yeni yönetime geçmişti ve Groupon’umu kabul etmedi
Formda “en az 15 kelime” şartı vardı; ne yaptıysam doğrulamayı geçemedim ve sonunda HTML’i incelemek zorunda kaldım
\wkelime karakteri,\bkelime sınırı,\sboşluktu; noktalama işaretlerine ise kelimenin tam anlamıyla hiç izin verilmiyordupatterngibi mevcut geçerlilik öznitelikleri güzel ama yeterli değilÖrneğin “parolayı tekrar girme” örneği
setCustomValidityolmadan dapatternözniteliğiyle uygulanabilir. Bunun için ilk girdi değerinden dinamik olarak bir düzenli ifade oluşturmak gerekirYazı çok uzamasın diye çözümleri karşılaştırmadım ama asıl nokta,
customValiditykullanınca doğrulamanın çok daha açık ve okunabilir hâle gelmesi. Burada daha iyi bir API büyük fark yaratıyor“En az 15 kelime” kısıtı da
value.split(/\s+/).length >= 15gibi çok daha okunaklı biçimde ifade edilebilirDaha az kullanılmasının bir nedeni var. Pek çok framework ve kütüphane sağlam ve stillendirilebilir doğrulama özellikleri sunuyor; bazıları çok gelişmiş ve genişletilebilir. Zorunda değilseniz kendinizi uğraştırmamak daha iyi
curlya da aynı form doğrulaması yerleşik olmayan başka bir araçla formu kurcalamaya çalışan biri her zaman olurİstemcinin doğrulama yapıp yapmadığına, doğru yapıp yapmadığına güvenemezsiniz; bu yüzden backend’in yine de girdiyi doğrulaması ve tüm alanların doğrulama hatalarıyla birlikte formu gösterebilmesi gerekir
Frontend doğrulaması yalnızca kullanıcıya yardımcı olmak içindir. Ama stillendirmek ya da gönderim sırasında backend’den tetiklemek istiyorsanız, sonuçta kendi stillendirmenizi de uygulamanız gerekir
Çok fazla tuzak var ve daha karmaşık kontrolleri kolayca desteklemek için sonunda bir kütüphane kullanıyorsunuz
Üstelik kütüphane kullanınca, duruma göre doğrulama kodunun bir kısmını frontend ile backend arasında paylaşma olasılığı da doğuyor
Özellikle bu yazı
useLayoutEffectile bir sorunu aşmaya çalışıyor gibi görünüyor; bu hafife alınacak bir şey değilHTML form doğrulamasında sevmediğim şeylerden biri, sayfa yüklenir yüklenmez çalışması. Örneğin hata durumu stilini buna bağlarsanız form baştan hata dolu şekilde yüklenir ve kullanıcıya göz korkutucu görünebilir
:user-invalidsözde sınıfı var. Ancak esnek olmayan yönleri olduğu için kullanım senaryosuna bağlı olarak yeterli olmayabilirhttps://developer.mozilla.org/en-US/docs/Web/CSS/:user-inval...
Script ile etrafından dolaşabilirsiniz ama o noktada bu özellik pek bir iş yapmış olmuyor. Daha yaygın benimsenmemesinin en büyük nedeninin de bu olduğunu düşünüyorum