调用 e.preventDefault() 后提交表单
Posted
技术标签:
【中文标题】调用 e.preventDefault() 后提交表单【英文标题】:Submit form after calling e.preventDefault() 【发布时间】:2014-04-17 07:33:02 【问题描述】:我在这里做一些简单的表单验证,但遇到了一个非常基本的问题。我有 5 个字段对用于名称和主菜(用于晚餐注册)。用户可以输入 1-5 对,但如果存在名称,则必须选择主菜。代码:
http://jsfiddle.net/eecTN/1/
<form>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
<input type="submit" value="Submit">
</form>
// Prevent form submit if any entrees are missing
$('form').submit(function(e)
e.preventDefault();
// Cycle through each Attendee Name
$('[name="atendeename[]"]', this).each(function(index, el)
// If there is a value
if ($(el).val())
// Find adjacent entree input
var entree = $(el).next('input');
// If entree is empty, don't submit form
if ( ! entree.val())
alert('Please select an entree');
entree.focus();
return false;
);
$('form').unbind('submit').submit();
);
错误消息有效,但每次都在提交表单。我知道这行有问题:
$('form').unbind('submit').submit();
...但我不确定我需要做什么。
【问题讨论】:
为什么要取消绑定提交表单??? 我看过这篇文章,但解决方案看起来很可疑,使用setTimeout
:***.com/questions/14866626/…
@d.danailov 所以它不会再次运行验证。请帮帮我——我需要做什么?
你为什么不改变它,让e.preventDefault()
只有在验证失败时才被调用?然后您可以删除带有.unbind().submit()
的行。
好的,其他的还可以,但这里也有想法jsfiddle.net/eecTN/9谢谢你的耐心
【参考方案1】:
使用原生element.submit()
绕过jQuery处理程序中的preventDefault,注意你的return语句只从每个循环返回,它不从事件处理程序返回
$('form').submit(function(e)
e.preventDefault();
var valid = true;
$('[name="atendeename[]"]', this).each(function(index, el)
if ( $(el).val() )
var entree = $(el).next('input');
if ( ! entree.val())
entree.focus();
valid = false;
);
if (valid) this.submit();
);
【讨论】:
【参考方案2】:$('form').submit(function(e)
var submitAllow = true;
// Cycle through each Attendee Name
$('[name="atendeename[]"]', this).each(function(index, el)
// If there is a value
if ($(el).val())
// Find adjacent entree input
var entree = $(el).next('input');
// If entree is empty, don't submit form
if ( ! entree.val())
alert('Please select an entree');
entree.focus();
submitAllow = false;
return false;
);
return submitAllow;
);
【讨论】:
【参考方案3】:问题是,即使你看到错误,你的return false
也会影响.each()
方法的回调......所以,即使有错误,你也到达了这条线
$('form').unbind('submit').submit();
并且表单已提交。
您应该创建一个变量,例如 validated
,并将其设置为 true。然后,在回调中,设置validated = false
,而不是return false
。
终于……
if (validated) $('form').unbind('submit').submit();
这样,只有在没有错误的情况下才会提交表单。
【讨论】:
【参考方案4】:最简单的解决方案是不调用e.preventDefault()
,除非验证确实失败。将该行移到内部 if
语句中,并删除带有 .unbind().submit()
的函数的最后一行。
【讨论】:
出于某种原因,我认为我需要先致电e.preventDefault()
,否则可能会出现某种竞争状况。感谢您的启发。
不,整个功能将在默认操作继续之前完成(或者如果您取消它,则不会继续)。如果您知道您从不想要特定事件的默认操作,那么将其作为显而易见的第一行是有意义的(例如,如果您想通过 Ajax 提交数据而不是通过表单提交,或者单击触发 JS 而不是执行标准导航的链接上的处理程序)。否则,把它放在条件逻辑中就可以了。
我过去很肯定一些严重 ajax 驱动的网站竞争条件是一个问题,所以第一行总是 e.preventDefault()。您是否 100% 确定按照您的建议进行操作是安全的?
@JamesNZ - 我很肯定它是安全的。在大量基于 Ajax 的站点中,如果在响应返回之前发出多个 Ajax 请求,竞争条件可能会成为问题,因为无法保证响应会以任何特定顺序返回 - 但即便如此,您仍然不需要 @ 987654325@ 作为第一行,因为当前同步代码块将在触发任何 Ajax 回调之前完成。也就是说,JS 将不会中断当前正在运行的函数来调用 Ajax 回调 - 或第二个事件处理程序或超时回调或其他。
@nnnnnn 好的。我会在下一个项目中仔细检查自己,但如果这不是问题,那就太好了。感谢您的回复。【参考方案5】:
抱歉耽搁了,但我会尽量做出完美的形式:)
我将添加计数验证步骤并检查每次不是.val()
。检查.length
,因为我认为在你的情况下是更好的模式。当然去掉unbind
函数。
My jsFiddle
当然是源码:
// Prevent form submit if any entrees are missing
$('form').submit(function(e)
e.preventDefault();
var formIsValid = true;
// Count validation steps
var validationLoop = 0;
// Cycle through each Attendee Name
$('[name="atendeename[]"]', this).each(function(index, el)
// If there is a value
if ($(el).val().length > 0)
validationLoop++;
// Find adjacent entree input
var entree = $(el).next('input');
var entreeValue = entree.val();
// If entree is empty, don't submit form
if (entreeValue.length === 0)
alert('Please select an entree');
entree.focus();
formIsValid = false;
return false;
);
if (formIsValid && validationLoop > 0)
alert("Correct Form");
return true;
else
return false;
);
【讨论】:
【参考方案6】:为什么不绑定提交按钮事件而不是表单本身呢?
如果您绑定按钮比表单本身更容易和更安全,因为除非您使用preventDefault()
,否则表单将主要提交
$("#btn-submit").on("click", function (e)
var submitAllow = true;
$('[name="atendeename[]"]', this).each(function(index, el)
// If there is a value
if ($(el).val())
// Find adjacent entree input
var entree = $(el).next('input');
// If entree is empty, don't submit form
if ( ! entree.val())
alert('Please select an entree');
entree.focus();
submitAllow = false;
return false;
);
if (submitAllow)
$("#form-attendee").submit();
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form-attendee">
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
Name: <input name="atendeename[]">
Entree: <input name="entree[]"><br>
<button type="button" id="btn-submit">Submit<button>
</form>
【讨论】:
因为点击提交按钮并不是提交表单的唯一方式。也因为即使在单击按钮时也没有验证,这也不会阻止提交。【参考方案7】:其实这似乎是正确的做法:
$('form').submit(function(e)
//prevent default
e.preventDefault();
//do something here
//continue submitting
e.currentTarget.submit();
);
【讨论】:
【参考方案8】:遇到了同样的问题,但在论坛等上没有找到直接的解决方案。最后,以下解决方案对我来说非常有效: 只需在事件处理函数中为表单“提交”事件实现以下逻辑:
document.getElementById('myForm').addEventListener('submit', handlerToTheSubmitEvent);
function handlerToTheSubmitEvent(e)
//DO NOT use e.preventDefault();
/*
your form validation logic goes here
*/
if(allInputsValidatedSuccessfully())
return true;
else
return false;
就这么简单; 注意:当表单 'submit' 事件的处理程序返回 'false' 时,表单不会提交到 html 标记的 action 属性中指定的 URI;直到和除非处理程序返回“真”;一旦您的所有输入字段都经过验证,事件处理程序将返回一个“真”,并且您的表单将被提交;
还请注意:if() 条件中的函数调用基本上是您自己的实现,以确保所有字段都经过验证,因此必须从那里返回“真”,否则为“假”
【讨论】:
【参考方案9】:绑定到按钮不会解决按下按钮之外的提交,例如按回车
【讨论】:
【参考方案10】:就我而言,有一场比赛,因为我需要 ajax 响应来填充隐藏字段并在填充后发送表单。我通过将 e.preventDefault() 放入条件来修复它。
var all_is_done=false;
$("form").submit(function(e)
if(all_is_done==false)
e.preventDefault();
do_the_stuff();
);
function do_the_stuf()
//do stuff
all_is_done=true;
$("form").submit();
【讨论】:
【参考方案11】:$(document).ready(function()
$('#myform').on('submit',function(event)
// block form submit event
event.preventDefault();
// Do some stuff here
...
// Continue the form submit
event.currentTarget.submit();
);
);
Source
【讨论】:
以上是关于调用 e.preventDefault() 后提交表单的主要内容,如果未能解决你的问题,请参考以下文章
引导验证(成功)后,表单使用默认方法而不是 ajax 提交。 e.preventDefault() 不起作用?
e.PreventDefault()未按预期触发,表单提交[重复]