如何从自定义 Web 组件中提取表单提交数据?

问题描述 投票:0回答:1

我需要了解表单提交如何从自定义 Web 组件中提取数据?

我尝试了以下步骤

1-将输入附加到

ShadoWroot

2-使用表单关联的概念,我将输入值和名称与表单联系起来
3-最后我提交表格以获得
FormData
.

不幸的是,它没有成功。我从

FormData

什么都得不到

// https://web.dev/more-capable-form-controls/
// https://webkit.org/blog/13711/elementinternals-and-form-associated-custom-elements/
// https://html.spec.whatwg.org/#custom-elements

let form = document.getElementById('frm');

// on form submit I need to recive form data from the input by getting name and its value
form.addEventListener('submit', (event) => {
    event.preventDefault();
    var formData = new FormData(form);
    // Display the key/value pairs
    for (const pair of formData.entries()) {
      console.log(`${pair[0]}, ${pair[1]}`);
    }

});

// I need here to assign value to form data using input name and input value
class SomeTextFieldElement extends HTMLElement {
    static formAssociated = true;
    internals;
    shadowRoot;
    constructor()
    {
        super();
        this.internals = this.attachInternals();
        this.shadowRoot = this.attachShadow({mode: 'closed', delegatesFocus: true});
        this.shadowRoot.innerHTML = "<input name='test' autofocus>";
        const input = this.shadowRoot.querySelector('input');
        input.addEventListener('change', () => {
            this.internals.setFormValue(input.value, input.value);
        });
    }
    formStateRestoreCallback(state, reason)
    {
        this.shadowRoot.querySelector('input').value = state;
    }
}
customElements.define('some-text-field', SomeTextFieldElement);
<form id='frm'>
  <some-text-field></some-text-field>
  <button type="submit">Submit</button>
</form>

javascript web-component form-data
1个回答
0
投票

@Danny 在评论中发布的链接有正确答案。 (感谢发布。)因此,以下代码片段不是我的代码,而是来自链接的 web.dev 文章中示例的代码。我已将它合并到您原始帖子中的代码示例中。

我注释掉了一些不影响将自定义组件的输入值插入到表单数据中的函数,因此很清楚哪些函数参与了表单数据插入过程。

let form = document.getElementById('frm');

// On form submit I need to receive form data from 
// the input by getting name and its value.
form.addEventListener('submit', (event) => {
  event.preventDefault();
  var formData = new FormData(form);
  // Display the key/value pairs
  for (const pair of formData.entries()) {
    console.log(`${pair[0]}, ${pair[1]}`);
  }
});

// I need here to assign value to form data using input name and input value
class SomeTextFieldElement extends HTMLElement {
  // [The following function is listed in the web.dev article.
  // It's not needed to add data to the form on form
  // submission but it's kept here to be uncommented.]

  // Useful values for <input>
  //static get observedAttributes() {
  //    return ['name', 'disabled', 'placeholder', 'value'];
  //}

  static formAssociated = true;
  internals;
  shadowRoot;
  constructor() {
    super();
    this.internals = this.attachInternals();
    this.shadowRoot = this.attachShadow({
      mode: 'closed',
      delegatesFocus: true
    });
    this.shadowRoot.innerHTML = "<input name='test' autofocus>";
    this.input = this.shadowRoot.querySelector('input');

    // Your original code. The 'change' event is not necessary
    // as the value of the 'input' element (named 'test')
    // is added to the form's data by the function 
    // 'handleFormData()' below.
    //const input = this.shadowRoot.querySelector('input');
    //input.addEventListener('change', () => {
    //    this.internals.setFormValue(input.value, input.value);
    //});

    // Keep reference to <form> for cleanup
    this._form = null;
    this._handleFormData = this.handleFormData.bind(this);
  }

  // FormData event is sent on <form> submission, 
  // so we can modify the data before transmission.
  // It has a .formData property, and that's all we need.
  handleFormData({
    formData
  }) {
    // Add our name and value to the form's submission 
    // data if we're not disabled.
    if (!this.input.disabled) {
      // https://developer.mozilla.org/en-US/docs/Web/API/FormData
      formData.append(this.input.name, this.input.value);
    }
  }

  // [The following function is listed in the web.dev article.
  // It's not needed to add data to the form on form
  // submission but it's kept here to be uncommented.]

  // Sync observed attributes to <input>
  //attributeChangedCallback(name, oldValue, newValue) {
  //    const value = name === 'disabled' ? this.hasAttribute('disabled') : newValue;
  //    this.input[name] = value;
  //}

  // Find the <form>, and attach the `formdata` listener.
  // This function is called when the following line is
  // executed by the browser.
  // customElements.define('some-text-field', SomeTextFieldElement);
  connectedCallback() {
    this._form = this.findContainingForm();
    if (this._form) {
      this._form.addEventListener('formdata', this._handleFormData);
    }
  }

  // [The following function is listed in the web.dev article.
  // It's not needed to add data to the form on form
  // submission but it's kept here to be uncommented.]

  // Remove the `formdata` listener if we're removed
  //disconnectedCallback() {
  //    if (this._form) {
  //        this._form.removeEventListener('formdata', this._handleFormData);
  //        this._form = null;
  //    }
  //}

  // Find the <form> we are contained in
  findContainingForm() {
    // Can only be in a form in the same "scope", ShadowRoot or Document
    const root = this.getRootNode();
    const forms = Array.from(root.querySelectorAll('form'));
    // We can only be in one <form>, so the first
    // one to contain us is the correct one.
    return forms.find((form) => form.contains(this)) || null;
  }
}

customElements.define('some-text-field', SomeTextFieldElement);
<form id='frm'>
  <label>Label</label>
  <some-text-field></some-text-field>
  <input type="text" name="normalInput" value="Normal input" />
  <button type="submit">Submit</button>
</form>

© www.soinside.com 2019 - 2024. All rights reserved.