You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Laravel中Bootstrap Validator触发验证后表单无法提交问题求助

Laravel + Bootstrap Validator 表单提交异常问题排查与解决

问题描述

我在Laravel项目里用Bootstrap Validator的时候遇到了个头疼的问题:表单触发验证后,就算把所有错误都修正了,表单还是提交不了;但要是没触发过验证,表单就能正常提交。

我的表单是用Laravel Collective Form构建的,代码如下:

{!! Form::open(["method" => "POST", "action" => "user\UserWalletController@transfer", "id" => "transferModal", "class" => "modal fade", "aria-labelledby" => "transferModal", "aria-hidden" => "true"]) !!} 
<div class="modal-dialog"> 
  <div class="modal-content"> 
    <div class="modal-header"> 
      <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> 
      <h5 class="modal-title colorOrange1">Transfer</h5> 
    </div> 
    <div class="modal-body"> 
      ... 
      <div class="row"> 
        <div class="col-xs-12"> 
          <div class="form-group"> 
            <div class="checkbox checkbox-primary"> 
              {!! Form::checkbox("agreeTermsOfUse", null, null, ["id" => "termsOfUse", "data-error" => "You must agree Terms of Use", "required"]) !!} 
              <label for="termsOfUse"> I agree with Terms Of Use </label> 
              <div class="help-block with-errors"></div> 
            </div> 
          </div> 
        </div> 
      </div> 
    </div> 
    <div class="modal-footer"> 
      <button type="button" class="btn btn-info" data-dismiss="modal">Close</button> 
      <button type="submit" id="submitTransferDetails" class="btn bgTeal1" name="operationBtn" value="transferFund">Submit</button> 
    </div> 
  </div> 
  <!-- /.modal-content --> 
</div> 
{!! Form::close() !!}

最初只写了一行验证代码:

$('#transferModal').validator();

后来我试着修改了JS代码,表单能提交了,但会疯狂输出上千次console.log("eooer")之后才完成提交,修改后的代码是这样的:

$('#transferModal').validator().on('submit', function (e) { 
  if ($("input[name='transferPasswordStatus']").val() == "true") { 
    if (e.isDefaultPrevented()) { 
      // handle the invalid form... 
    } else { 
      console.log("eooer"); 
      $(this).submit(); 
    } 
  } else if ($("input[name='transferPasswordStatus']").val() == "false") { 
    alert("Password mismatch"); 
  } 
});

问题根源

兄弟,你这段修改后的代码里藏着个大坑:在submit事件处理函数里调用$(this).submit(),这会再次触发表单的submit事件,而这个事件又会进入你写的处理函数,再次调用$(this).submit(),无限循环下去,直到浏览器因为递归次数过多强制停止,这就是为什么你会看到上千次的console.log输出。

至于最初的代码里验证后无法提交,大概率是因为Bootstrap Validator在验证通过后没有正确放行原生的提交事件,或者你的表单结构里有其他影响事件冒泡的因素,但修改后的代码直接引入了更严重的递归问题。

解决方案

我们需要避免递归触发submit事件,同时保证验证通过后能正常提交表单,这里给你两种可行的方案:

方案一:使用原生DOM元素的submit方法

jQuery的submit()方法会触发绑定的事件监听,而原生DOM的submit()不会,所以我们可以改成调用原生方法:

$('#transferModal').validator().on('submit', function (e) { 
  const passwordStatus = $("input[name='transferPasswordStatus']").val();
  if (passwordStatus === "true") { 
    if (e.isDefaultPrevented()) { 
      // 处理验证不通过的情况,比如提示用户修正错误
      return;
    } 
    // 调用原生submit,不会触发jQuery的submit事件监听,完美避免递归
    this.submit(); 
  } else if (passwordStatus === "false") { 
    alert("Password mismatch"); 
    // 阻止默认提交行为,避免表单提交
    e.preventDefault();
  } 
});

方案二:先阻止默认行为,验证通过后手动提交(更清晰)

这种方式逻辑更直观,先阻止所有默认提交,再根据条件判断是否提交:

$('#transferModal').validator().on('submit', function (e) { 
  // 先阻止默认提交行为,把控制权握在自己手里
  e.preventDefault();
  const passwordStatus = $("input[name='transferPasswordStatus']").val();

  if (passwordStatus === "false") { 
    alert("Password mismatch"); 
    return;
  }

  // 检查表单是否已经通过Bootstrap Validator的验证
  if (!e.isDefaultPrevented()) { 
    // 验证通过,提交表单
    this.submit(); 
  } else {
    // 验证不通过,这里可以加自定义提示,比如显示错误汇总
    alert("请修正表单中的错误后再提交");
  }
});

额外注意事项

  • 确保你的Bootstrap Validator版本是最新的,旧版本可能存在一些事件处理的bug
  • 检查表单里的其他元素是否有阻止事件冒泡的代码(比如return false),这也可能导致验证后无法提交
  • 如果遇到浏览器原生验证和Bootstrap Validator冲突的情况,可以给提交按钮添加formnovalidate属性,禁用原生验证

内容的提问来源于stack exchange,提问作者chengwei

火山引擎 最新活动