फ़ॉर्म के और बेहतर कंट्रोल

नए इवेंट और कस्टम एलिमेंट एपीआई की मदद से, फ़ॉर्म में हिस्सा लेना अब और भी आसान हो गया है.

आर्थर इवान्स

कई डेवलपर कस्टम फ़ॉर्म कंट्रोल बनाते हैं, ताकि वे ऐसे कंट्रोल उपलब्ध करा सकें जो ब्राउज़र में बिल्ट-इन नहीं हैं या फिर बिल्ट-इन फ़ॉर्म कंट्रोल की मदद से, जितना हो सके उतना लुक और स्टाइल के मुताबिक बदलाव किया जा सकता है.

हालांकि, पहले से मौजूद एचटीएमएल फ़ॉर्म कंट्रोल की सुविधाओं को कॉपी करना मुश्किल हो सकता है. कुछ ऐसी सुविधाओं के बारे में सोचें जो <input> एलिमेंट को किसी फ़ॉर्म में जोड़ने पर, अपने-आप मिलती हैं:

  • फ़ॉर्म के कंट्रोल की सूची में, इनपुट अपने-आप जुड़ जाता है.
  • इनपुट की वैल्यू, फ़ॉर्म के साथ अपने-आप सबमिट हो जाती है.
  • यह इनपुट, फ़ॉर्म की पुष्टि में शामिल होता है. :valid और :invalid स्यूडोक्लास का इस्तेमाल करके, इनपुट को स्टाइल किया जा सकता है.
  • जब फ़ॉर्म को रीसेट किया जाता है, जब फ़ॉर्म को फिर से लोड किया जाता है या जब ब्राउज़र, फ़ॉर्म की एंट्री को ऑटोमैटिक भरने की कोशिश करता है, तो इनपुट को इसकी सूचना दी जाती है.

आम तौर पर, कस्टम फ़ॉर्म कंट्रोल में इनमें से कुछ सुविधाएं होती हैं. डेवलपर, JavaScript की कुछ सीमाओं को दूर कर सकते हैं, जैसे कि फ़ॉर्म सबमिशन में हिस्सा लेने के लिए, फ़ॉर्म में छिपा हुआ <input> जोड़ना. हालांकि, अन्य सुविधाओं को अकेले JavaScript में कॉपी नहीं किया जा सकता.

वेब की दो नई सुविधाओं की मदद से, पसंद के मुताबिक फ़ॉर्म कंट्रोल बनाना और मौजूदा कस्टम कंट्रोल की सीमाओं को हटाना आसान है:

  • formdata इवेंट की मदद से, आर्बिट्रेरी JavaScript ऑब्जेक्ट, फ़ॉर्म सबमिशन में हिस्सा ले सकता है. इससे, छिपे हुए <input> का इस्तेमाल किए बिना, फ़ॉर्म में डेटा जोड़ा जा सकता है.
  • फ़ॉर्म से जुड़े कस्टम एलिमेंट एपीआई की मदद से, कस्टम एलिमेंट पहले से मौजूद फ़ॉर्म कंट्रोल की तरह काम कर सकते हैं.

इन दोनों सुविधाओं का इस्तेमाल करके, बेहतर काम करने वाले नए तरह के कंट्रोल बनाए जा सकते हैं.

इवेंट-आधारित एपीआई

formdata इवेंट, लो-लेवल का एपीआई है. इसकी मदद से, किसी भी JavaScript कोड को फ़ॉर्म सबमिट करने में मदद मिलती है. यह तरीका इस तरह काम करता है:

  1. आपको जिस फ़ॉर्म से इंटरैक्ट करना है उसमें formdata इवेंट लिसनर जोड़ा जाता है.
  2. जब कोई उपयोगकर्ता 'सबमिट करें' बटन पर क्लिक करता है, तो फ़ॉर्म एक formdata इवेंट फ़ायर करता है. इसमें एक FormData ऑब्जेक्ट शामिल होता है, जिसमें सबमिट किया जा रहा पूरा डेटा होता है.
  3. फ़ॉर्म सबमिट करने से पहले, formdata लिसनर को डेटा जोड़ने या उसमें बदलाव करने का मौका मिलता है.

formdata इवेंट लिसनर में एक वैल्यू भेजने का एक उदाहरण यहां दिया गया है:

const form = document.querySelector('form');
// FormData event is sent on <form> submission, before transmission.
// The event has a formData property
form.addEventListener('formdata', ({formData}) => {
  // https://developer.mozilla.org/docs/Web/API/FormData
  formData.append('my-input', myInputValue);
});

Glitch पर दिए गए हमारे उदाहरण की मदद से इसे आज़माएं. एपीआई को काम करता हुआ देखने के लिए, Chrome 77 या उसके बाद के वर्शन पर इसे चलाएं.

वेबसाइट का अलग-अलग ब्राउज़र पर चलना

ब्राउज़र सहायता

  • 5
  • 12
  • 4
  • 5

सोर्स

फ़ॉर्म से जुड़े कस्टम एलिमेंट

किसी भी तरह के कॉम्पोनेंट के साथ, इवेंट-आधारित एपीआई का इस्तेमाल किया जा सकता है. हालांकि, यह सिर्फ़ सबमिशन की प्रोसेस के साथ इंटरैक्ट करने की अनुमति देता है.

स्टैंडर्ड फ़ॉर्म कंट्रोल, सबमिट करने के अलावा फ़ॉर्म की लाइफ़साइकल के कई हिस्सों में शामिल होते हैं. फ़ॉर्म से जुड़े कस्टम एलिमेंट का मकसद, कस्टम विजेट और पहले से मौजूद कंट्रोल के बीच के अंतर को कम करना है. फ़ॉर्म से जुड़े कस्टम एलिमेंट, स्टैंडर्ड फ़ॉर्म एलिमेंट की कई सुविधाओं से मेल खाते हैं:

  • जब किसी फ़ॉर्म से जुड़े कस्टम एलिमेंट को <form> में रखा जाता है, तो वह फ़ॉर्म के साथ अपने-आप जुड़ जाता है. जैसे, ब्राउज़र से मिलने वाला कंट्रोल.
  • एलिमेंट को <label> एलिमेंट का इस्तेमाल करके लेबल किया जा सकता है.
  • एलिमेंट, फ़ॉर्म के साथ अपने-आप सबमिट होने वाली वैल्यू सेट कर सकता है.
  • एलिमेंट में एक फ़्लैग सेट किया जा सकता है. इससे पता चलता है कि इसमें मान्य इनपुट है या नहीं. अगर किसी फ़ॉर्म कंट्रोल में अमान्य इनपुट है, तो फ़ॉर्म सबमिट नहीं किया जा सकता.
  • एलिमेंट, फ़ॉर्म के लाइफ़साइकल के अलग-अलग हिस्सों के लिए कॉलबैक दे सकता है—जैसे कि फ़ॉर्म बंद होने या उसकी डिफ़ॉल्ट स्थिति पर रीसेट होने पर.
  • यह एलिमेंट, :disabled और :invalid जैसे फ़ॉर्म कंट्रोल के लिए, स्टैंडर्ड सीएसएस स्यूडोक्लास के साथ काम करता है.

इसमें कई सुविधाएं होती हैं! इस लेख में सभी ज़रूरी जानकारी नहीं दी गई है. हालांकि, इसमें फ़ॉर्म से आपके कस्टम एलिमेंट को इंटिग्रेट करने के लिए ज़रूरी बुनियादी बातें बताई गई हैं.

फ़ॉर्म से जुड़े कस्टम एलिमेंट तय करना

किसी कस्टम एलिमेंट को फ़ॉर्म से जुड़े कस्टम एलिमेंट में बदलने के लिए, कुछ और चरण पूरे करने होंगे:

  • अपने कस्टम एलिमेंट क्लास में स्टैटिक formAssociated प्रॉपर्टी जोड़ें. यह ब्राउज़र को एलिमेंट को फ़ॉर्म कंट्रोल की तरह इस्तेमाल करने के लिए कहता है.
  • फ़ॉर्म कंट्रोल के लिए, setFormValue() और setValidity() जैसे अन्य तरीकों और प्रॉपर्टी का ऐक्सेस पाने के लिए, एलिमेंट के attachInternals() तरीके को कॉल करें.
  • फ़ॉर्म कंट्रोल के साथ काम करने वाली सामान्य प्रॉपर्टी और तरीके जोड़ें, जैसे कि name, value, और validity.

यहां बताया गया है कि वे आइटम किसी बेसिक कस्टम एलिमेंट परिभाषा में कैसे फ़िट होते हैं:

// Form-associated custom elements must be autonomous custom elements--
// meaning they must extend HTMLElement, not one of its subclasses.
class MyCounter extends HTMLElement {

  // Identify the element as a form-associated custom element
  static formAssociated = true;

  constructor() {
    super();
    // Get access to the internal form control APIs
    this.internals_ = this.attachInternals();
    // internal value for this control
    this.value_ = 0;
  }

  // Form controls usually expose a "value" property
  get value() { return this.value_; }
  set value(v) { this.value_ = v; }

  // The following properties and methods aren't strictly required,
  // but browser-level form controls provide them. Providing them helps
  // ensure consistency with browser-provided controls.
  get form() { return this.internals_.form; }
  get name() { return this.getAttribute('name'); }
  get type() { return this.localName; }
  get validity() {return this.internals_.validity; }
  get validationMessage() {return this.internals_.validationMessage; }
  get willValidate() {return this.internals_.willValidate; }

  checkValidity() { return this.internals_.checkValidity(); }
  reportValidity() {return this.internals_.reportValidity(); }

  …
}
customElements.define('my-counter', MyCounter);

रजिस्टर होने के बाद, इस एलिमेंट का इस्तेमाल उन जगहों पर किया जा सकता है जहां ब्राउज़र के दिए गए फ़ॉर्म कंट्रोल का इस्तेमाल किया जाता है:

<form>
  <label>Number of bunnies: <my-counter></my-counter></label>
  <button type="submit">Submit</button>
</form>

वैल्यू सेट करना

attachInternals() वाला तरीका, ऐसा ElementInternals ऑब्जेक्ट दिखाता है जो फ़ॉर्म कंट्रोल एपीआई का ऐक्सेस देता है. इनमें से सबसे बुनियादी तरीका setFormValue() तरीका है, जो कंट्रोल की मौजूदा वैल्यू को सेट करता है.

setFormValue() वाले तरीके में वैल्यू के तीन टाइप में से कोई एक लिया जा सकता है:

  • स्ट्रिंग की वैल्यू.
  • File ऑब्जेक्ट.
  • FormData ऑब्जेक्ट. एक से ज़्यादा वैल्यू पास करने के लिए, FormData ऑब्जेक्ट का इस्तेमाल किया जा सकता है. उदाहरण के लिए, क्रेडिट कार्ड का इनपुट कंट्रोल, कार्ड नंबर, खत्म होने की तारीख, और पुष्टि करने के लिए कोड पास कर सकता है.

सामान्य वैल्यू सेट करने के लिए:

this.internals_.setFormValue(this.value_);

एक से ज़्यादा वैल्यू सेट करने के लिए, कुछ ऐसा किया जा सकता है:

// Use the control's name as the base name for submitted data
const n = this.getAttribute('name');
const entries = new FormData();
entries.append(n + '-first-name', this.firstName_);
entries.append(n + '-last-name', this.lastName_);
this.internals_.setFormValue(entries);

इनपुट की पुष्टि करना

आपका कंट्रोल, इंंटरनल ऑब्जेक्ट पर setValidity() तरीके को कॉल करके, फ़ॉर्म की पुष्टि करने में भी हिस्सा ले सकता है.

// Assume this is called whenever the internal value is updated
onUpdateValue() {
  if (!this.matches(':disabled') && this.hasAttribute('required') &&
      this.value_ < 0) {
    this.internals_.setValidity({customError: true}, 'Value cannot be negative.');
  }
  else {
    this.internals_.setValidity({});
  }
  this.internals.setFormValue(this.value_);
}

फ़ॉर्म से जुड़े कस्टम एलिमेंट को :valid और :invalid स्यूडोक्लास के साथ स्टाइल किया जा सकता है. यह स्टाइल, पहले से मौजूद फ़ॉर्म कंट्रोल की तरह ही होती है.

लाइफ़साइकल कॉलबैक

फ़ॉर्म से जुड़े कस्टम एलिमेंट एपीआई में, फ़ॉर्म की लाइफ़साइकल से जुड़ने के लिए, अतिरिक्त लाइफ़साइकल कॉलबैक का सेट शामिल होता है. कॉलबैक ज़रूरी नहीं हैं: कॉलबैक सिर्फ़ तब लागू करें, जब लाइफ़साइकल में उस समय आपके एलिमेंट को कुछ करने की ज़रूरत हो.

void formAssociatedCallback(form)

यह तब कॉल किया जाता है, जब ब्राउज़र, एलिमेंट को किसी फ़ॉर्म एलिमेंट से जोड़ता है या एलिमेंट को किसी फ़ॉर्म एलिमेंट से अलग कर देता है.

void formDisabledCallback(disabled)

इसे एलिमेंट की disabled स्थिति के बाद कॉल किया जाता है, क्योंकि इस एलिमेंट के disabled एट्रिब्यूट को जोड़ा या हटाया गया है. ऐसा तब भी किया जाता है, जब <fieldset> पर disabled स्थिति बदली गई है, जो इस एलिमेंट का पूर्वज है. disabled पैरामीटर, एलिमेंट की नई बंद की गई स्थिति के बारे में बताता है. उदाहरण के लिए, यह एलिमेंट अपने शैडो डीओएम में बंद होने पर एलिमेंट को बंद कर सकता है.

void formResetCallback()

फ़ॉर्म रीसेट होने के बाद इसे कॉल किया जाता है. एलिमेंट को खुद को किसी तरह की डिफ़ॉल्ट स्थिति पर रीसेट कर देना चाहिए. <input> एलिमेंट के लिए, इसमें आम तौर पर value प्रॉपर्टी को इस तरह सेट किया जाता है कि वह मार्कअप में सेट किए गए value एट्रिब्यूट से मैच करे. इसके अलावा, चेकबॉक्स के मामले में, checked प्रॉपर्टी को checked एट्रिब्यूट से मैच करने के लिए सेट किया जाता है.

void formStateRestoreCallback(state, mode)

इन दो स्थितियों में से किसी एक में कॉल किया गया:

  • जब ब्राउज़र, एलिमेंट की स्थिति को पहले जैसा करता है (उदाहरण के लिए, नेविगेशन के बाद या ब्राउज़र के रीस्टार्ट होने पर). इस मामले में mode आर्ग्युमेंट "restore" है.
  • जब ब्राउज़र की इनपुट-सहायता सुविधाएं, जैसे कि फ़ॉर्म अपने-आप भरने की सुविधा, कोई वैल्यू सेट करती है. इस मामले में mode आर्ग्युमेंट "autocomplete" है.

पहले आर्ग्युमेंट का टाइप, इस बात पर निर्भर करता है कि setFormValue() वाले तरीके को कैसे कॉल किया गया. ज़्यादा जानकारी के लिए, फ़ॉर्म का स्टेटस वापस लाना देखें.

फ़ॉर्म की स्थिति को पहले जैसा किया जा रहा है

कुछ स्थितियों में—जैसे किसी पेज पर वापस नेविगेट करते समय या ब्राउज़र को रीस्टार्ट करते समय, ब्राउज़र फ़ॉर्म को उसी स्थिति में वापस लाने की कोशिश कर सकता है जिसमें उपयोगकर्ता ने उसे छोड़ा था.

फ़ॉर्म से जुड़े कस्टम एलिमेंट के लिए, वापस लाई गई स्थिति, setFormValue() तरीके को पास की गई वैल्यू से मिलती है. तरीके में एक वैल्यू पैरामीटर जोड़ा जा सकता है, जैसा कि पिछले उदाहरण में दिखाया गया है. इसके अलावा, दो पैरामीटर इस्तेमाल करके भी इस तरीके को कॉल किया जा सकता है:

this.internals_.setFormValue(value, state);

value से, कंट्रोल की सबमिट की जा सकने वाली वैल्यू के बारे में पता चलता है. वैकल्पिक state पैरामीटर, कंट्रोल की स्थिति को इंटरनल दिखाता है. इसमें ऐसा डेटा शामिल हो सकता है जो सर्वर को नहीं भेजा जाता. state पैरामीटर में वही टाइप होता है जो value पैरामीटर का होता है. यह कोई स्ट्रिंग, File या FormData ऑब्जेक्ट हो सकता है.

state पैरामीटर तब काम आता है, जब सिर्फ़ वैल्यू के आधार पर कंट्रोल की स्थिति को पहले जैसा नहीं किया जा सकता. उदाहरण के लिए, मान लें कि आप कई मोड वाला कलर पिकर बनाते हैं: कोई पैलेट या आरजीबी कलर व्हील. सबमिट करने लायक value, कैननिकल फ़ॉर्म में चुना गया रंग होगा, जैसे कि "#7fff00". हालांकि, कंट्रोल को किसी खास स्टेटस पर वापस लाने के लिए, आपको यह भी जानना होगा कि वह किस मोड में था, ताकि state "palette/#7fff00" की तरह दिखे.

this.internals_.setFormValue(this.value_,
    this.mode_ + '/' + this.value_);

स्टोर किए गए स्टेटस की वैल्यू के आधार पर, आपके कोड को अपनी स्थिति पहले जैसी करनी होगी.

formStateRestoreCallback(state, mode) {
  if (mode == 'restore') {
    // expects a state parameter in the form 'controlMode/value'
    [controlMode, value] = state.split('/');
    this.mode_ = controlMode;
    this.value_ = value;
  }
  // Chrome currently doesn't handle autofill for form-associated
  // custom elements. In the autofill case, you might need to handle
  // a raw value.
}

आसान कंट्रोल (उदाहरण के लिए, संख्या इनपुट) के मामले में, हो सकता है कि कंट्रोल को उसकी पिछली स्थिति पर वापस लाने के लिए, वैल्यू काफ़ी हो. अगर setFormValue() को कॉल करते समय state को छोड़ दिया जाता है, तो वैल्यू formStateRestoreCallback() को पास कर दी जाती है.

formStateRestoreCallback(state, mode) {
  // Simple case, restore the saved value
  this.value_ = state;
}

काम करने वाला उदाहरण

नीचे दिए गए उदाहरण में, फ़ॉर्म से जुड़े कस्टम एलिमेंट की कई सुविधाओं को एक साथ रखा गया है. एपीआई को काम करता हुआ देखने के लिए, Chrome 77 या उसके बाद के वर्शन पर इसे चलाएं.

सुविधा की पहचान करने की सुविधा

सुविधा की पहचान करने की सुविधा का इस्तेमाल करके, यह पता लगाया जा सकता है कि formdata इवेंट और फ़ॉर्म से जुड़े कस्टम एलिमेंट उपलब्ध हैं या नहीं. फ़िलहाल, किसी भी सुविधा के लिए कोई भी पॉलीफ़िल रिलीज़ नहीं किया गया है. दोनों ही मामलों में, फ़ॉर्म में कंट्रोल की वैल्यू लागू करने के लिए, छिपे हुए फ़ॉर्म एलिमेंट को जोड़ा जा सकता है. फ़ॉर्म से जुड़े कस्टम एलिमेंट की ज़्यादा बेहतर सुविधाओं में, कई चीज़ों को पॉलीफ़िल करना मुश्किल या नामुमकिन हो सकता है.

if ('FormDataEvent' in window) {
  // formdata event is supported
}

if ('ElementInternals' in window &&
    'setFormValue' in window.ElementInternals.prototype) {
  // Form-associated custom elements are supported
}

नतीजा

formdata इवेंट और फ़ॉर्म से जुड़े कस्टम एलिमेंट में, नए टूल का इस्तेमाल करके कस्टम फ़ॉर्म कंट्रोल बनाए जा सकते हैं.

formdata इवेंट से आपको कोई नई सुविधा नहीं मिलती. हालांकि, इससे आपको एक इंटरफ़ेस मिलता है. इसकी मदद से, सबमिट की प्रोसेस में फ़ॉर्म डेटा को जोड़ा जा सकता है. ऐसा करने के लिए, छिपा हुआ <input> एलिमेंट बनाने की ज़रूरत नहीं होती.

फ़ॉर्म से जुड़े कस्टम एलिमेंट एपीआई में कस्टम फ़ॉर्म कंट्रोल बनाने के लिए नई सुविधाएं मिलती हैं. ये कंट्रोल, पहले से मौजूद फ़ॉर्म कंट्रोल की तरह काम करते हैं.

Unsplash पर ओडम प्रवत की हीरो इमेज.