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

किसी फ़ॉर्म में कस्टम कंट्रोल की वैल्यू दिखाने के लिए, छिपे हुए <input> का इस्तेमाल न करें. फ़ॉर्म से जुड़े कस्टम एलिमेंट (एफ़एसीई) का इस्तेमाल करें: formAssociated और ElementInternals के साथ, एलिमेंट अपनी वैल्यू सबमिट करता है, पुष्टि करने की प्रोसेस में हिस्सा लेता है, और फ़ॉर्म की स्थिति को नेटिव तौर पर दिखाता है.

class RatingInput extends HTMLElement {
  // MANDATORY: opt in. Without this, attachInternals() form APIs are unavailable.
  static formAssociated = true;

  #internals;
  #value = '';

  constructor() {
    super();
    this.#internals = this.attachInternals();
    this.attachShadow({ mode: 'open', delegatesFocus: true });
  }

  connectedCallback() {
    // Validate initial state once attributes (such as `required`) are present.
    this.#validate();
  }

  get value() { return this.#value; }
  set value(v) {
    this.#value = v;
    // Push the value into the owning <form> for submission.
    this.#internals.setFormValue(v);
    this.#validate();
  }

  #validate() {
    if (this.hasAttribute('required') && !this.#value) {
      // Mark invalid and supply the native validation message + anchor.
      this.#internals.setValidity(
        { valueMissing: true },
        'Please choose a rating.',
        this.shadowRoot.querySelector('[tabindex]'),
      );
    } else {
      this.#internals.setValidity({}); // clear
    }
  }

  // Optional FACE lifecycle hooks:
  formResetCallback() { this.value = ''; }
  formDisabledCallback(disabled) {
    // Disable internal controls so they leave the tab order and ignore clicks.
    // Do NOT toggle `disabled` on `this`, or a `<fieldset disabled>` toggle will
    // leave the host permanently stuck with its own `disabled` attribute.
    for (const el of this.shadowRoot.querySelectorAll('button')) {
      el.disabled = disabled;
    }
  }
  formStateRestoreCallback(state) { this.value = state; }
}
customElements.define('rating-input', RatingInput);

खास बातें:

  • static formAssociated = true ज़रूरी है; यह फ़ॉर्म से जुड़े ElementInternals तरीकों और formXxxCallback लाइफ़साइकल को अनलॉक करता है.
  • setFormValue(value) को सबमिट किया जाता है. इसके लिए, किसी छिपे हुए इनपुट की ज़रूरत नहीं होती. एक से ज़्यादा वैल्यू वाले कंट्रोल के लिए, FormData पास करें.
  • setValidity(flags, message, anchor), नेटिव कंस्ट्रेंट वैलिडेशन के साथ इंटिग्रेट होता है: अमान्य होने पर फ़ॉर्म सबमिट नहीं होगा, :invalid/:valid लागू होगा, और रिपोर्ट पर ऐंकर एलिमेंट को फ़ोकस मिलेगा. इस समस्या को हल करने के लिए, setValidity({}) पर कॉल करें. इंटरैक्शन के बारे में जानकारी देने वाली :user-valid/:user-invalid सूडो-क्लास, सभी ब्राउज़र पर फ़ॉर्म से जुड़े एलिमेंट के लिए एक जैसी नहीं होती हैं. इसलिए, इन पर भरोसा करने से पहले यह पुष्टि कर लें कि ये काम करती हैं या नहीं. यह न मानें कि ये उपयोगकर्ता के इंटरैक्शन को उसी तरह ट्रैक करती हैं जिस तरह नेटिव कंट्रोल के लिए करती हैं.
  • formResetCallback, formDisabledCallback, और formStateRestoreCallback को लागू करें, ताकि रीसेट करने, fieldset[disabled], और बैक/फ़ॉरवर्ड ऑटोमैटिक तरीके से भरने की सुविधा को पहले जैसा करने पर, एलिमेंट नेटिव कंट्रोल की तरह काम करे. formDisabledCallback(disabled) में, होस्ट पर disabled सेट करने के बजाय, इंटरनल कंट्रोल बंद करें या उन्हें टैब ऑर्डर से हटाएं और इनपुट को अनदेखा करें. कॉलबैक में होस्ट एट्रिब्यूट सेट करने से, पैरंट <fieldset> के फिर से चालू होने पर, उसे फिर से चालू नहीं किया जा सकता. साथ ही, होस्ट पहले से ही :disabled से अपने-आप मैच हो जाता है.
  • डिस्पैच किए गए इवेंट के लिए, प्लैटफ़ॉर्म के नियमों का पालन करें. साथ ही, कस्टम इवेंट के बजाय, पहले से मौजूद input और change इवेंट को प्राथमिकता दें. input तब ट्रिगर होता है, जब उपयोगकर्ता की कार्रवाई (टाइप करना, स्लाइडर को खींचना और छोड़ना) की वजह से वैल्यू बदलती है; change बदलावों की हर स्ट्रीम के लिए एक बार ट्रिगर होता है, जब उपयोगकर्ता कोई कार्रवाई करता है (स्लाइडर को छोड़ना, फ़ील्ड को धुंधला करना). इन्हें क्रमशः InputEvent और Event से बनाएं.

फ़ॉलबैक रणनीतियां

इस सुविधा पर भरोसा करने से पहले, static formAssociated की मदद से यह पता लगाएं कि यह सुविधा काम करती है या नहीं: 'attachInternals' in HTMLElement.prototype && 'setFormValue' in ElementInternals.prototype. जहां यह उपलब्ध न हो वहां कंट्रोल की वैल्यू के साथ सिंक किए गए, विज़ुअल तौर पर छिपे हुए नेटिव <input> पर वापस जाएं, ताकि फ़ॉर्म अब भी सबमिट हो सके. यह एक ऐसा मामला है जहां छिपे हुए इनपुट पैटर्न को सही ठहराया जा सकता है.