如何确保 JavaScript .submit() 遵守附加到表单的事件处理程序
How to ensure a JavaScript .submit() respects event handlers attached to the form
注意
所以我实际上在写出问题的同时设法解决了这个问题,但我想无论如何我都会 post 以防它帮助其他人(对 Stack Overflow 的简短搜索表明没有其他人似乎问了完全相同的问题)
所以我有一个带有 Web 组件的表单,该表单通过 JavaScript 处理,如下所示:
<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 组件,我希望能够 'submit' 将表单切换到 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
事件处理程序不 运行 并且形式简单地 post 没有任何 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}));
})
}
}
澄清一下,答案是使用 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}));
})
}
}
注意 所以我实际上在写出问题的同时设法解决了这个问题,但我想无论如何我都会 post 以防它帮助其他人(对 Stack Overflow 的简短搜索表明没有其他人似乎问了完全相同的问题)
所以我有一个带有 Web 组件的表单,该表单通过 JavaScript 处理,如下所示:
<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 组件,我希望能够 'submit' 将表单切换到 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
事件处理程序不 运行 并且形式简单地 post 没有任何 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}));
})
}
}
澄清一下,答案是使用 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}));
})
}
}