HTML फ़ॉर्म वैलिडेशन का कम उपयोग
(expressionstatement.com)- HTML फ़ॉर्म में
required,type="email",pattern,maxlength,setCustomValidityजैसी नेटिव वैलिडेशन सुविधाएँ पहले से मौजूद हैं, लेकिन उनकी वास्तविक उपयोगिता उनकी क्षमता की तुलना में कम है - सबसे शक्तिशाली
setCustomValidityमनचाही वैलिडेशन लॉजिक और जटिल मामलों को संभाल सकता है, लेकिन यह केवल DOM method के रूप में उपलब्ध है, इसलिए यह declarative components के साथ अच्छी तरह मेल नहीं खाता - React जैसे वातावरण में initial value validation को सही रखने के लिए
useRef,useLayoutEffect,onChangeआपस में उलझ जाते हैं, और वही validation logic initial rendering और change handler में duplicate हो जाना आसान है - अगर
custom-validityजैसी attribute-based abstraction हो, तो async username duplication check या password confirmation जैसी state और input के बीच dependency वाली validation को एक ही जगह व्यक्त किया जा सकता है - नेटिव फ़ॉर्म वैलिडेशन का कम adoption, feature की कमी से ज़्यादा API usability की समस्या के करीब है, और अगर declarative API HTML spec में आ जाए तो इसके उपयोग की संभावना बढ़ सकती है
HTML फ़ॉर्म वैलिडेशन पहले से क्या देता है
- खाली input को रोकने का सबसे आसान तरीका
requiredattribute जोड़ना है - input constraints को मोटे तौर पर तीन तरीकों से लगाया जा सकता है
type="email",type="number",type="url"जैसे input type का उपयोगpattern,maxlengthजैसी constraint attributes का उपयोग- input के
setCustomValidityDOM method का उपयोग
setCustomValidityमनचाही validation logic और जटिल मामलों को संभाल सकता है, इसलिए यह सबसे शक्तिशाली तरीका है- पहले दो तरीके HTML attributes के रूप में declare किए जा सकते हैं, लेकिन
setCustomValidityकी खास बात यह है कि इसमें method call की ज़रूरत होती है - DOM attributes और properties के अंतर पर संदर्भ सामग्री के रूप में Attributes vs Properties लिंक किया गया है
जहाँ setCustomValidity असुविधाजनक हो जाता है
setCustomValidityकिसी corresponding HTML attribute के बिना केवल method के रूप में exposed है- अगर इसमें string दी जाए तो input invalid state में चला जाता है, और browser उसी string को validation failure reason के रूप में दिखाता है
- अगर empty string दी जाए, तो दूसरी constraints न होने पर input valid state में रहता है
requiredजैसा behavior सीधे implement करने के लिए value बदलने पर हर बारsetCustomValidityको call करना पड़ता है- लेकिन input शुरुआत में valid state में होता है, इसलिए component reset होने के तुरंत बाद submit button दबाया जाए तो form submission pass हो सकता है
- ऐसा इसलिए क्योंकि value खाली होने पर भी change event होने से पहले validation code नहीं चलता
- initial value तक सही रखने के लिए component mount के समय भी वही validation चलानी पड़ती है
Declarative components में बढ़ता boilerplate
- initial value validation तक संभालने पर code जल्दी repetitive और असुविधाजनक हो जाता है
- खास तौर पर तीन समस्याएँ सामने आती हैं
- validation logic
onChangehandler और initial rendering stage में duplicate हो जाती है - initial validation code input element से दूर होने के कारण cohesion कम हो जाती है, और केवल एक तरफ बदलाव होने का जोखिम रहता है
useRef,useLayoutEffect,onChangeका संयोजन input बढ़ने के साथ ज़रूरत से ज़्यादा भारी हो जाता है, और जब केवल कुछ inputs मेंcustomValidityइस्तेमाल हो तो और भ्रम पैदा होता है
- validation logic
- यह जटिलता declarative components में शुद्ध imperative API को संभालते समय खास तौर पर दिखाई देती है
CustomValidityके लिए नेटिव validation attributes की तरह कोई declarative input attribute नहीं है जिससे उसका value set किया जा सके- जब API असुविधाजनक हो, तो feature शक्तिशाली होने के बावजूद adoption कम रह सकती है, और यही नेटिव फ़ॉर्म वैलिडेशन के कम उपयोग का मुख्य कारण है
missing piece: custom-validity attribute
- ज़रूरी रूप input पर सीधे दिया जा सकने वाला
custom-validityजैसा declarative attribute है - declarative frameworks में इस attribute से validation state को input element के पास रखा जा सकता है
- अभी
HTML Specमें वास्तविकcustom-validityमौजूद नहीं है - demo उद्देश्य के लिए userland implementation से इस behavior की नकल की जा सकती है
- production-ready component example के रूप में एक और ज़्यादा पूर्ण implementation दिया गया है
Async validation और inputs के बीच dependency
- वास्तविक applications में validation स्थानीय checks से ज़्यादा जटिल हो सकती है
- username input के लिए server से यह पुष्टि करनी होती है कि नाम पहले से उपयोग में है या नहीं, और request के दौरान form valid state में नहीं होना चाहिए
- उदाहरण में खाली input रोकने के लिए
requiredका उपयोग होता है, और loading state व response result के आधार परcustomValidityसे input को invalid state में रखा जाता है - implementation दो हिस्सों से मिलकर बनी है
- username uniqueness check request state को
react-queryकेuseQueryसे manage करना customValidityprop लेने वाले custom<Input />component का उपयोग
- username uniqueness check request state को
- यह तरीका loading, error, success सहित पूरे async validation flow को एक ही attribute में व्यक्त कर सकता है
- अतिरिक्त उदाहरण में ऐसा form है जिसमें डाला गया password दोबारा दर्ज करना होता है, और यह एक-दूसरे पर निर्भर input fields की validation को संभालता है
निष्कर्ष
setCustomValidityविभिन्न validation आवश्यकताओं को संभालने वाला एक शक्तिशाली tool है- वास्तविक उपयोगिता तय करने वाली चीज़ सिर्फ feature का होना नहीं, बल्कि ऐसा API होना है जो उसे इस्तेमाल करना आसान बनाए
custom-validityजैसी declarative abstraction नेटिव फ़ॉर्म वैलिडेशन को अधिक स्वाभाविक तरीके से इस्तेमाल करने देती है- उम्मीद की जा सकती है कि ऐसा feature कभी HTML spec में नेटिव रूप से शामिल हो
1 टिप्पणियां
Hacker News की राय
पिछली बार जब मैंने देखा था, तब भी आजकल के web browsers built-in HTML validation messages की शक्ल को style करने नहीं देते थे https://stackoverflow.com/questions/5328883/how-do-i-style-t...
अगर Chrome और Firefox कम से कम OS platform UI guidelines का पालन करके इन्हें
title=""tooltip की तरह सिस्टम द्वारा दिखाए गए जैसा बनाते, तो बात कुछ कम खटकती। लेकिन Chrome पीले/नारंगी icon, सफेद background पर काला text, और fixed rounded-corner speech bubble इस्तेमाल करता है, जो मौजूदा project की aesthetic से बुरी तरह टकराता है।पुराने Chrome में vendor-prefixed pseudo-element selector के जरिए validation message styling की अनुमति थी, लेकिन वह feature हटाने के बाद फिर वापस नहीं लाया गया। यह मेरी मनमानी झुंझलाहटों की सूची में चला जाता है, जैसे “native HTML combobox दे दो” और “यह अभी भी checkbox list की जगह इस्तेमाल में मुश्किल Ctrl+click box क्यों है”
validitystate पढ़कर अपनी इच्छा से render करना काफी आसान है।असली समस्या इस validity state में बदलावों को सही-सही subscribe करना कठिन होना है। validity events मौजूद तो हैं, लेकिन हमेशा fire नहीं होते।
form.reset()call करने याinput.value = '...'की तरह form state को programmatically बदलने पर ये events trigger नहीं होते।मुझे लगता है यह अलग से जांचने और web platform के लिए propose करने लायक अच्छा विषय है।
सबसे बड़ा और लागू करने में आसान होने के बावजूद कम इस्तेमाल होने वाला तरीका
email,number,urlजैसे specifictypeattribute values का उपयोग करना है।mobile पर optimal keyboard दिखाकर user experience को काफी बेहतर किया जा सकता है।
type=numberसे बचता हूं और इसकी जगहtype=text inputmode=numericइस्तेमाल करता हूं। इससे वे arrow buttons नहीं लगते जिनकी ज्यादातर users को number input में जरूरत नहीं होती, और iOS पर keyboard भी बेहतर होता है।typeset नहीं किया गया होता।dateinput में भी मैंने ऐसे बहुत मामले देखे हैं। हर frontend library का अपना date widget होता है, और उनमें से कई छोटे screens पर बहुत खराब दिखते हैं।उस एक widget के लिए JS और CSS जोड़ना पड़ता है, और कुछ तो jQuery पर निर्भर होते हैं। बेशक कुछ में बहुत सारी settings होती हैं, लेकिन बहुत छोटे cost में हर जगह ठीक-ठाक और native जैसा दिखने वाला widget मिल जाता है, आम तौर पर requirements भी पूरी हो जाती हैं, और updates या CDN की चिंता किए बिना इसे भूल सकते हैं।
सामान्य input से भी यह मुश्किल से संभव है, लेकिन special inputs और भी कम events support करते हैं।
मेरा product सिर्फ इसलिए accessibility audit पास नहीं कर पाया क्योंकि वह native HTML form validation इस्तेमाल करता था, और आधिकारिक recommendation था कि अपनी validation layer implement करें। मैं भी उस recommendation से सहमत हूँ
native HTML validation में बहुत कमियाँ हैं, और सच कहूँ तो visual customization सबसे बड़ी चिंता भी नहीं है। हालांकि यह ताबूत में आखिरी कील जैसा ज़रूर है
उदाहरण के लिए, अगर प्रति field कई errors एक साथ दिखाने हों, तो strings को जोड़ने के अलावा कोई रास्ता नहीं है। जैसे “नंबर चाहिए। symbol चाहिए। 10 characters से लंबा होना चाहिए”, लेकिन यह user experience के लिए भी खराब है और accessibility के लिए भी। क्योंकि accessibility tree में जोड़ी गई string को navigate नहीं किया जा सकता। यह implementation-specific समस्या नहीं, बल्कि spec की ही समस्या है। users के लिए validation errors की whack-a-mole खेलना मज़ेदार नहीं है, इसलिए कई errors एक साथ दिखा पाना चाहिए
browser-dependent होना भी खराब है। आप control नहीं कर सकते, और implementations भी आम तौर पर बेहद खराब हैं। Chrome focus पर popup दिखाता है, जो popup है, modal जैसा दिखता है, और सभी form errors एक साथ नहीं दिखा सकता, इसलिए अपने आप में accessibility के लिहाज से अच्छा नहीं है। महत्वपूर्ण जानकारी popup में न दिखाना accessibility की बुनियादी बात है, लेकिन browser के पास actual document में बाधा डाले बिना करने को बहुत कुछ नहीं है
किसी specific field से संबंधित न होने वाले पूरे form के errors के लिए भी custom validation चाहिए। जैसे “A और B fields compatible नहीं हैं” वाला error, और ऐसे में consistent validation approach रखना बेहतर है
अगर native input types में fit न होने वाला custom input है, तो consistency के लिए hidden input रखना पड़ता है, और यह भी accessibility तोड़ता है। इसे ठीक करना आखिरकार अपनी accessibility-friendly validation system बनाने जितना ही मुश्किल है
customValidityAPI imperative है और इस्तेमाल में झंझट वाला है। जब तक आप “यह field valid नहीं है” जैसे भयानक messages नहीं चाहते, custom validity इस्तेमाल न करना लगभग कोई option नहीं है। इसलिए HTML form validation बहुत खराब हैफिर भी मुझे लगता है कि native validation mechanism का उपयोग करने लायक value है। error messages के लिए native validity tooltip का उपयोग करना ज़रूरी नहीं है; आप
input.validityकेValidityStateको सीधे पढ़कर अपने तरीके से messages render कर सकते हैं और ज़रूरत हो तो कई errors दिखा सकते हैंbrowsers बेहतर हो सकते हैं, और standardized approach इस्तेमाल करने पर आप उसका फायदा उठा सकते हैं। “popup इस्तेमाल न करें तो accessibility टूटती है” जैसा निष्कर्ष अजीब लगता है, लेकिन अगर audit का जवाब देना है तो शायद उसी रास्ते जाना पड़े
किसी specific field से संबंधित न होने वाले errors को handle करने की techniques भी हैं। मेरे project में, दूसरे fields से संबंधित न होने वाले custom errors render करने के लिए invisible read-only input बनाने वाला
HiddenValidationInputcomponent इस्तेमाल होता है। बस conditionally render करना होता है, इसलिए व्यवहार में काफी उपयोगी हैमैं पूरी तरह सहमत हूँ कि
customValidityAPI imperative और झंझट वाला है। मैंने इसी हिस्से को cover करने वाला लेख लिखा था, और उम्मीद है कि समय के साथ इसमें भी सुधार होगाChrome का crude और कम-accessible design Chrome की समस्या है, इसलिए मैं bug report file करूँगा
“spec” से क्या आपका मतलब यह है? https://html.spec.whatwg.org/multipage/dom.html#concept-elem...
validation message कैसे display किया जाना चाहिए, इसे define करने वाला हिस्सा नहीं दिखता। यहाँ तक कि message होना अनिवार्य है, ऐसा भी कुछ नहीं है
सच कहूँ तो, ऐसी specs लिखने वाले लोग reality से कटे हुए लगते हैं और शायद वे खुद उन चीज़ों का इस्तेमाल नहीं करते जिन्हें उन्होंने specify किया है। बहुत simple चीज़ों के लिए यह काम करता है, लेकिन जैसे ही form evolve होना शुरू करता है, अंत में समझ आता है कि सब कुछ खुद लिखना ही बेहतर है
JS इस्तेमाल करना शुरू करते ही validation attributes से छेड़छाड़ करने की बजाय सब कुछ code में करना कहीं ज़्यादा आसान हो जाता है
अगर checkbox का label है, तो अच्छा होगा कि label में
forattribute लगाया जाए ताकि label click करके checkbox on/off किया जा सके। निजी तौर पर यह मुझे सबसे ज्यादा खटकने वाली चीज़ों में से एक है, हालांकि शायद सिर्फ मुझे ही ऐसा लगता होinputकोlabelमें wrap करने से भी काम करता है। समझ नहीं आता लोग दोनों को अलग-अलग रखने की तरफ क्यों झुकते हैंऔर यह भी नहीं समझ आता कि browsers ने इन्हें अलग करना क्यों शुरू किया। मुझे लगता है text में checkbox और radio शामिल होने के बजाय, checkbox और radio में text शामिल होना चाहिए
React इस्तेमाल न करने वाला simple example यहाँ है
https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectE...
HTML फ़ॉर्म validation बेहतरीन है। बस इसमें एक बहुत बड़ा trap है
Android के लिए Firefox में यह काम नहीं करता
https://bugzilla.mozilla.org/show_bug.cgi?id=1510450
लाल रंग में दिखाए गए controls के error message न देख पाने वाले 1% से कम users के लिए standard को ignore करने लायक बात नहीं है। जितनी ज़्यादा websites इसका इस्तेमाल करेंगी, Mozilla पर browser ठीक करने का दबाव उतना ही बढ़ेगा
यह Chrome या Safari द्वारा standardization से पहले implement की गई WebMIDI जैसी API नहीं है, बल्कि मूल HTML5 spec का हिस्सा है
खासकर यह देखते हुए कि accessibility software इस्तेमाल करने वाले लोग site को ठीक से use कर सकें, इस पर कितना कम समय लगाया जाता है। अगर UC Browser तक की बात करने को तैयार नहीं हैं, तो मुझे नहीं लगता कि ऐसे मुद्दे में इसका ज़िक्र बहुत मायने रखता है
फिर भी दूसरे extensions के साथ uBlock Origin इस्तेमाल कर पाना एक मजबूत advantage है
[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1884282
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1897707
अगर validation implement ही नहीं किया गया होता तो शायद बेहतर होता, लेकिन यह तो सचमुच गड़बड़ है। कुछ साल पहले लंबी और दर्दनाक debugging के बाद मुझे यह पता चला, और मुझे यकीन है कि मैं ऐसा अनुभव करने वाला न पहला था न आख़िरी
search करने से पहले तक मैं सोच भी नहीं पाया कि मैं क्या miss कर रहा हूँ, और यह काफी shocking था। अपनी validation बनाना ठीक है, लेकिन इसे काम करना चाहिए
ध्यान रखना चाहिए कि इसका इस्तेमाल जरूरत से ज़्यादा न हो
हाल ही में मैं Groupon से refund लेने की कोशिश कर रहा था। क्योंकि जिस business के लिए Groupon खरीदा था, उसका management बदल गया था और उन्होंने मेरा Groupon मानने से इनकार कर दिया था
form में “कम से कम 15 शब्द” की शर्त थी, लेकिन किसी भी तरह validation pass नहीं हो रहा था, इसलिए आखिर में मुझे HTML inspect करना पड़ा
\wword character था,\bword boundary था,\swhitespace था, और punctuation को सचमुच बिल्कुल allow नहीं किया गया थाpatternजैसी मौजूदा validity attributes अच्छी हैं, लेकिन पर्याप्त नहींउदाहरण के लिए “password repeat input” वाला example
setCustomValidityके बिना भीpatternattribute से implement किया जा सकता है। इसके लिए पहले input value से dynamically regular expression बनाना होगाarticle बहुत लंबा न हो जाए इसलिए मैंने solutions compare नहीं किए, लेकिन मुख्य बात यह है कि
customValidityइस्तेमाल करने पर validation कहीं ज़्यादा clear और readable हो जाती है। यहाँ बेहतर API बड़ा फर्क डालती है“कम से कम 15 शब्द” constraint भी
value.split(/\s+/).length >= 15जैसे कहीं ज़्यादा साफ़ तरीके से express किया जा सकता हैइसका कम इस्तेमाल होने की वजह है। कई frameworks और libraries मजबूत और styling-friendly validation features देती हैं, और कुछ तो बहुत sophisticated और extensible हैं। अगर ज़रूरी न हो, तो खुद को बेवजह परेशान न करना ही बेहतर है
curl, या ऐसे किसी दूसरे tool से form से छेड़छाड़ करने की कोशिश करेगा जिसमें वही form validation built-in नहीं हैआप trust नहीं कर सकते कि client ने validation की है या सही की है, इसलिए backend को अब भी input validate करना होगा और सभी fields की validation errors के साथ form दिखा पाने में सक्षम होना होगा
frontend validation सिर्फ user की मदद के लिए है। लेकिन अगर उसे style करना हो या submit पर backend से trigger करना हो, तो आखिरकार अपनी styling भी implement करनी पड़ेगी
traps बहुत ज़्यादा हैं, और ज़्यादा complex checks को आसानी से support करने के लिए आखिर में library इस्तेमाल करनी पड़ती है
ऊपर से library इस्तेमाल करने पर कुछ मामलों में frontend और backend के बीच validation code का हिस्सा share करने की संभावना भी बनती है
खासकर यह article
useLayoutEffectसे एक problem को bypass करता हुआ दिखता है, जो हल्के में करने वाली चीज़ नहीं हैHTML form validation में मुझे नापसंद चीज़ों में से एक यह है कि यह page load होते ही run हो जाती है। उदाहरण के लिए अगर error state style को इससे जोड़ दें, तो form शुरू से ही errors से भरा हुआ load होता है और user को डराने वाला लग सकता है
:user-invalidpseudo-class है। हालांकि इसमें flexibility की कमी है, इसलिए use case के हिसाब से यह पर्याप्त न भी हो सकती हैhttps://developer.mozilla.org/en-US/docs/Web/CSS/:user-inval...
script से bypass किया जा सकता है, लेकिन उस point पर यह feature बहुत कुछ कर नहीं रहा होता। मुझे लगता है कि इसके ज़्यादा व्यापक रूप से adopt न होने की सबसे बड़ी वजह यही है