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

hwamh0ep  于 2023-02-28  发布在  Java
关注(0)|答案(1)|浏览(124)

我需要了解表单提交如何从自定义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>
cu6pst1q

cu6pst1q1#

@Danny在评论中发布的链接有正确的答案。(感谢发布。)因此,下面的代码片段不是我的代码,而是来自链接的www.example.com文章中的示例代码。我已经将其合并到您原始帖子中的代码示例中。web.dev article. I've incorporated it into your code sample from your original post.
我注解掉了一些不影响将定制组件的输入值插入表单数据的函数,这样就可以清楚地看到哪些函数参与表单数据插入过程。

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>

相关问题