【问题标题】:How to ensure a JavaScript .submit() respects event handlers attached to the form如何确保 JavaScript .submit() 尊重附加到表单的事件处理程序
【发布时间】:2019-07-25 12:51:10
【问题描述】:

注意 所以我实际上在写出问题的同时设法解决了这个问题,但我想无论如何我都会发帖以防它帮助其他人(在 Stack Overflow 上的简短搜索表明,似乎没有其他人问过完全相同的问题)


所以我有一个带有通过 JavaScript 处理的 Web 组件的表单,如下所示:

<form id="myform">
  <input type="text" value="example" tabindex="1" />
  <web-component tabindex="2"></web-component>
  <input type="submit" tabindex="3" />
</form>

<script>
let form = document.getElementById('myform');

form.addEventListener('submit' (e) => {
  e.preventDefault();

  console.log('Form is posting');

  // Handle form stuff here
})
</script>

对于我的 Web 组件,我希望能够在将表单切换到 Web 组件并按“Enter”时“提交”表单,这样我在 Web 组件中就有了以下处理程序:

class WebComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') form.submit();
    })
  }
}

我遇到的问题是form.submit() 提交了表单,但没有触发被监控的事件,导致form 事件处理程序无法运行,并且表单只是在没有任何 JS 验证的情况下发布。我让表单工作的第一个想法是将表单提交函数更改为命名函数,例如:

form.addEventListener('submit', handleFormSubmission);

myComponent.addEventListener('keydown', (e) => {
  if(e.code === 'Enter') handleFormSubmission();
})

但是这里的问题是,Web 组件不一定能用于多个表单,或者需要在每次调用它时添加一个事件处理程序,以确保它与与形式。这必须在组件之外完成,并且确实降低了可读性。

我考虑的另一个选项是在表单中搜索 input[type=submit]button[type=submit] 并触发点击,但这对我来说似乎有些笨拙。

经过一番搜索,我发现了dispatchEvent,它会触发submit 事件,而不是简单地触发submit(),如下所示:

class WebComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') form.dispatchEvent(new Event('submit'));
    })
  }
}

现在我 非常 接近 - submit 处理程序和 console.log 触发,但 e.preventDefault() 不受尊重,这意味着如果我的 JS 验证想要终止出于任何原因提交,它不能...默认情况下。

更多的搜索(即实际上很费心阅读规范,而不是全速前进并在墙上扔泥看看有什么粘着)我意识到Event 构造函数需要一个可选对象进行设置,这样您就可以拥有(例如)new Event('submit', {bubbles: true, cancelable: true})。最后,它起作用了:

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

form.addEventListener('submit' (e) => {
  e.preventDefault();

  console.log('Form is posting');

  // Handle form stuff here
});

class WebComponent extends HTMLElement {
  constructor() {
    ...

    let form = this.closest('form');

    this.addEventListener('keydown', (e) => {
      if(form && e.code === 'Enter') form.dispatchEvent(new Event('submit', {cancelable: true}));
    })
  }
}

【问题讨论】:

    标签: javascript events submit preventdefault


    【解决方案1】:

    澄清一下,答案是使用dispatchEvent创建一个新的Event并将cancelable设置为true而不是.submit()

    例如

    let form = document.getElementById('myform');
    
    form.addEventListener('submit' (e) => {
      e.preventDefault();
    
      console.log('Form is posting');
    
      // Handle form stuff here
    });
    
    class WebComponent extends HTMLElement {
      constructor() {
        ...
    
        let form = this.closest('form');
    
        this.addEventListener('keydown', (e) => {
          if(form && e.code === 'Enter') form.dispatchEvent(new Event('submit', {cancelable: true}));
        })
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-25
      • 2012-11-01
      • 2016-12-18
      相关资源
      最近更新 更多