jQuery的$(form).submit();不应该触发表单标签内的onSubmit吗?

43

我有以下内容:

<script type="text/javascript">
function CancelFormButton(button) {
    $(button.form).submit();
}
</script>

<form onsubmit="alert('here');">
<input type="button" value="Cancel" onClick="CancelFormButton(this);" />
</form>

当我点击“取消”按钮时,form标签中的onsubmit不会被触发。

相反,这行代码可以成功提交表单:$(button.form).submit();,但跳过了form标签中的alert('here');

这是正确的吗,还是我做错了什么?顺便说一句,在这种情况下,我需要这个功能,但我想知道是否会在某个浏览器中触发onsubmit。

9个回答

58

抱歉,误解了你的问题。

根据Javascript - capturing onsubmit when calling form.submit()

最近有人问我:“为什么我使用javascript提交表单时,表单的onsubmit事件没有被触发?”

答案是:当前的浏览器不遵循HTML规范中的这一部分。该事件只会在用户激活时触发,而在代码激活时不会触发。

(强调添加)。

注意:“由用户激活”也包括点击提交按钮(可能包括从回车键产生的默认提交行为,但我还没有尝试过)。同时,如果您使用代码单击提交按钮,则此事件也将不会被触发。


这仍然没有触发表单的onsubmit事件...这正常吗? - Darryl Hein
是的,this.form 是有效和正确的,并且在所有浏览器中都可以工作。https://dev59.com/BLitzYgBFxS5KdRj6TDL 另外,您没有回答问题。 - Darryl Hein
1
再回答问题而不是改变问题!现在我看起来像个傻瓜:( 但是,感谢解释。我想知道“current”是什么。 - Darryl Hein
2
链接似乎不存在了? - aldrin
尝试在异步表单验证后执行.submit(),你会发现为什么onSubmit没有被触发。(你喜欢无限循环吗?)我需要验证文件在AWS S3上是否有更改,这意味着旧的验证必须默认返回“false”,而不是在有效时返回“true”,然后分叉远程检查,如果成功,则使用.submit()提交表单。 - Scott
显示剩余4条评论

32
这个解决方法可以修复@Cletus发现的问题。您可以参考这里
function submitForm(form) {
    //get the form element's document to create the input control with
    //(this way will work across windows in IE8)
    var button = form.ownerDocument.createElement('input');
    //make sure it can't be seen/disrupts layout (even momentarily)
    button.style.display = 'none';
    //make it such that it will invoke submit if clicked
    button.type = 'submit';
    //append it and click it
    form.appendChild(button).click();
    //if it was prevented, make sure we don't get a build up of buttons
    form.removeChild(button);
}

适用于所有现代浏览器。
可在选项卡/子窗口中使用(是的,即使在IE<9中也可以)。
而且是原生的!

只需将表单元素的DOM引用传递给它,它将确保所有附加的侦听器、onsubmit和(如果没有被阻止)最终提交表单。


我尝试了不同的解决方案,只有这个可以在所有浏览器上触发提交事件并检查表单的有效性(显示错误消息)http://dabblet.com/gist/97a733d9c787dcf99cff - mems
2
如果您已经在使用jQuery,这里是相应的jQuery代码: var form = $('youFormSelector'); var submitBtn = $('<input type="submit"></input>'); submitBtn.appendTo(form); submitBtn.click(); submitBtn.remove(); - Frank Fajardo
@FrankFajardo,你在这里做了一些假设。
如果form在不同的document中,appendTo()会为您克隆元素(我使用open()制作了一个弹出窗口并尝试了appendTo();但没有起作用)。
jQuery的click()将调用提交(我在anchor上测试过,页面没有更改)。 然而,即使你是对的,你也可以比你现在的代码更简洁,否则你可能还是继续使用我的代码。 function submitForm(form) { $('<input>', {type:'submit', style:'display:none'}).appendTo(form).click().remove(); }
- Hashbrown
感谢 @Hashbrown 的评论。我不太确定你为什么说我假设 jQuery 的 click() 将调用 submit。据我从你的原始代码中了解,是输入的 type 属性提交了表单。我的代码似乎可以在同一文档中的表单上工作(这是 SO 的上下文)。另外,我不太明白您关于克隆的评论。$('<input/>').appendTo(target) 不就等同于首先创建 $('<input/>') 然后将其附加到目标吗? - Frank Fajardo
没关系。我的意思是,对我来说,jQuery的click()似乎不会调用元素的点击。它似乎只会触发附加的点击事件。所以<a>不会重新定位,<input type="submit">不会提交等等。另一点是我们编写的jQuery代码将适用于所有表单,但不适用于运行时之外的文档中存在的表单。也就是说,在框架和子窗口中,您需要首先进行“采用”。我原始脚本中的魔法是form.ownerDocument,从一开始就在本地环境中创建元素。 - Hashbrown
显示剩余2条评论

8
我认为在某些情况下希望有这种行为是合理的,但我会认为不触发表单提交的代码应该是默认行为(始终如此)。假设您想使用`
`标签捕获表单的提交:
$("form").submit(function(e){
    e.preventDefault();
});

然后对输入进行一些验证。如果代码可以触发提交处理程序,您将无法包含。

$("form").submit()

在此处理程序内这样做会导致无限循环(相同的处理程序将被调用,防止提交,验证并重新提交)。您需要能够在提交处理程序内手动提交表单,而不触发相同的处理程序。
我知道这并没有直接回答问题,但是这个页面上有很多其他关于如何攻击此功能的答案,我觉得需要指出这一点(并且它太长了不能作为评论)。

6

我的简单解决方案:

$("form").children('input[type="submit"]').click();

这对我很有效。


这假设您有提交按钮。 - artemave
1
如果您有一个提交按钮,那么onsubmit将会被触发。我认为问题出在type=button onclick=...上。 - Chris Noe

2

trigger('submit')不起作用,因为onSubmit方法没有被触发。以下代码对我有效,在使用此代码时调用onSubmit方法:

$("form").find(':submit').click();


1
尝试在您的函数中触发()事件:
$("form").trigger('submit'); // and then... do submit()

不行,也不会触发提交。 - Darryl Hein
2
$("form").trigger("submit") 和 $("form").submit() 是一样的,只是第二个是一个快捷方式。 - tandrewnichols

1
代替

$("form").submit()

尝试这个。
 $("<input type='submit' id='btn_tmpSubmit'/>").css('display','none').appendTo('form');
 $("#btn_tmpSubmit").click();

0

我几年前发现了这个问题。

最近我尝试“重写”提交方法。以下是我的代码:

window.onload= function (){
for(var i= 0;i<document.forms.length;i++){
    (function (p){
        var form= document.forms[i];
        var originFn= form.submit;
        form.submit=function (){
            //do something you like
            alert("submitting "+form.id+" using submit method !");
            originFn();
        }
        form.onsubmit= function (){
            alert("submitting "+form.id+" with onsubmit event !");
        }
    })(i);


}

}

<form method="get" action="" id="form1">
<input type="submit" value="提交form1" />
<input type="button" name="" id="" value="button模拟提交1" onclick="document.forms[0].submit();" /></form>

在IE中可以,但由于与“cletus”相同的原因,在其他浏览器中失败了。


0
最简单的解决方法是创建一个“临时”的提交类型输入,并触发点击:
var submitInput = $("<input type='submit' />");
$("#aspnetForm").append(submitInput);
submitInput.trigger("click");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接