调用 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()未按预期触发,表单提交[重复]

为什么e.preventDefault()会在提交时刷新页面?

基于ajax响应提交导致循环,如何正确调用原生提交?

提交成功后Jquery清除表单[重复]

提交后重置 HTML 表单