当输入验证失败时,Angularjs会阻止表单提交

Posted

技术标签:

【中文标题】当输入验证失败时,Angularjs会阻止表单提交【英文标题】:Angularjs prevent form submission when input validation fails 【发布时间】:2013-04-22 04:55:14 【问题描述】:

我正在使用带有一些客户端输入验证的 angularjs 编写一个简单的登录表单,以检查用户名和密码是否不为空且长度超过三个字符。见以下代码:

<form name="loginform" novalidate ng-submit="login.submit()" class="css-form">
    <fieldset>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-user"></i></span>
            <input type="text" ng-model="login.username" name="username" required ng-minlength="3" placeholder="username" />
        </div>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-lock"></i></span>
            <input type="password" ng-model="login.password" name="password" required ng-minlength="3" placeholder="" />
        </div>

        <div class="control-group">
            <input class="btn" type="submit" value="Log in">
        </div>

    </fieldset>
</form>

还有控制器:

var controller = function($scope) 

    $scope.login = 
        submit: function() 

            Console.info($scope.login.username + ' ' + $scope.login.password);
        
    

;

问题是即使输入无效,login.submit 函数也会被调用。是否可以防止这种行为?

作为旁注,我可以提到我也使用 bootstrap 和 requirejs。

【问题讨论】:

***.com/questions/18516001/… 我们可以在没有表单标签的情况下使用它并且仍然 form.valid 可以在 ng-click 上工作! 【参考方案1】:

你可以这样做:

<form name="loginform" novalidate ng-submit="loginform.$valid && login.submit()">

无需控制器检查。

【讨论】:

这应该是公认的答案。无需检查控制器中的任何内容 我不同意“不需要控制器检查”。如果我们在提交函数中发生额外的验证检查怎么办。 执行指令中的附加验证。使用 $setValidity 更新验证。 @b1tsh1ft 最好始终知道验证的当前状态,而不是在提交时弄清楚。这就是 Angular 验证的重点。当范围不知道无效状态时,您无法获得任何视觉指示。 我已经尝试过这种方法,但它似乎对两者都进行了评估(即它不会在 &amp;&amp; 之后将布尔值短路我已尝试将值作为提交的一部分传递并确认值本身是“假”【参考方案2】:

将提交按钮更改为:

<button type="submit" ng-disabled="loginform.$invalid">Login</button>

【讨论】:

很好的答案。你摇滚! 如果在输入字段获得焦点时按回车,您仍然可以提交表单! @Red:见上面的评论。 虽然禁用按钮通常是解决此问题的最佳方法,但这不是 OP 要求的。 结合这种技术为用户提供视觉反馈和@Yashua 回答以防止表单提交是完美的。谢谢!【参考方案3】:

所以 TheHippo 建议的答案对我不起作用,相反,我最终将表单作为参数发送给函数,如下所示:

<form name="loginform" novalidate ng-submit="login.submit(loginForm)" class="css-form">

这使得表单在控制器方法中可用:

$scope.login = 
    submit : function(form) 
        if(form.$valid)....
    

【讨论】:

我遇到了同样的问题。不过,使用你的方法是有效的。 这比接受的答案略好,因为 form.$valid 检查是在 JS 中完成的,而不是在 html 中。 但是,我认为您不需要通过 loginForm 来提交功能:我认为 $scope.loginform 应该在 JS 中可用(至少对我来说是这样),因此您可以替换 form .$valid 与 $scope.loginform.$valid.【参考方案4】:

您的表单会自动作为对象放入 $scope。可以通过$scope[formName]访问

以下示例适用于您的原始设置,无需在 ng-submit 中将表单本身作为参数传递。

var controller = function($scope) 

    $scope.login = 
        submit: function() 
            if($scope.loginform.$invalid) return false;

        
    

;

工作示例:http://plnkr.co/edit/BEWnrP?p=preview

【讨论】:

如果您使用“作为控制器”表示法而不是 $scope,您将如何访问表单? @masimakopoulos:您可以简单地使用if(this.loginform.$invalid).. 代替,但是在HTML 中您必须为表单命名&lt;form name="ctrl.loginform" ..。这是假设您在控制器作为语法中使用&lt;div ng-controller="controller as ctrl"..。谢谢@JoshCaroll【参考方案5】:

HTML:

<div class="control-group">
    <input class="btn" type="submit" value="Log in" ng-click="login.onSubmit($event)">
</div>

在您的控制器中:

$scope.login = 
    onSubmit: function(event) 
        if (dataIsntValid) 
            displayErrors();
            event.preventDefault();
        
        else 
            submitData();
        
    

【讨论】:

真的有必要在 onsubmit 方法中做检查吗?这意味着您必须检查输入是否符合标记(通过角度)和 js 代码中的所有标准。在我看来,当输入无效时,角度不应该调用 onsubmit。请参阅benlesh.com/2012/11/angular-js-form-validation.html 说“在整个表单为 $valid 之前无法调用 ng-submit” 如果表单有效,您还可以禁用按钮以不允许提交。您也可以使用 ng-submit 表单。如果 Angular 不处理表单验证,那么 event.preventDefault() 是要走的路,停止表单提交。 @RunarHalse 确实有必要进行检查。我同意你的看法,不应该这样。在您链接的示例中未调用 onsubmit 方法的原因是因为该示例没有设置 novalidate 。浏览器阻止事件引发,而不是 Angular。这是他的例子,上面有 nobalidate:plnkr.co/edit/R0C8XA?p=preview。注意表单提交。 完美正是我想要的,一种使用 angular 阻止表单提交的方法【参考方案6】:

虽然不是 OPs 问题的直接解决方案,但如果您的表单在 ng-app 上下文中,但您希望 Angular 完全忽略它,您可以使用 ngNonBindable 指令显式执行此操作:

<form ng-non-bindable>
  ...
</form>

【讨论】:

【参考方案7】:

只是为了补充上面的答案,

我有 2 个常规按钮,如下所示。 (任何地方都没有 type="submit")

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>
<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

无论我怎么尝试,一旦表单有效就按回车,“清除表单”按钮被调用,清除整个表单。

作为一种解决方法,

我必须添加一个已禁用和隐藏的虚拟提交按钮。 并且这个虚拟按钮必须位于所有其他按钮的顶部,如下所示

<button type="submit" ng-hide="true" ng-disabled="true">Dummy</button>

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>

<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

好吧,我的意图是永远不要在 Enter 上提交,所以上面给出的 hack 可以正常工作。

【讨论】:

您也可以通过从表单中删除 on ng-submit 属性来停止按 Enter 提交【参考方案8】:

我知道这是一个旧线程,但我想我也会做出贡献。我的解决方案类似于已标记为答案的帖子。一些内联 javascript 检查可以解决问题。

ng-click="form.$invalid ? alert('Please correct the form') : saveTask(task)"

【讨论】:

如果在输入字段获得焦点时按回车,您仍然可以提交表单!【参考方案9】:

我知道它已经很晚了,但我想分享我制作的整洁的东西。 我创建了一个 ng-validate 指令来挂钩表单的 onsubmit,然后如果 $eval 为 false,它会发出 prevent-default:

app.directive('ngValidate', function() 
  return function(scope, element, attrs) 
    if (!element.is('form'))
        throw new Error("ng-validate must be set on a form elment!");

    element.bind("submit", function(event) 
        if (!scope.$eval(attrs.ngValidate, '$event': event))
            event.preventDefault();
        if (!scope.$$phase)
            scope.$digest();            
    );
  ;
);

在您的 html 中:

<form name="offering" method="post" action="offer" ng-validate="<boolean expression">

【讨论】:

感谢分享,需要做一个普通的表单帖子,但先用angularjs验证,ng_validate="formName.$valid" 工作

以上是关于当输入验证失败时,Angularjs会阻止表单提交的主要内容,如果未能解决你的问题,请参考以下文章

使用JS对form的内容验证失败后阻止提交

角度模糊验证阻止提交单独的表单

提交时的表单验证 - angularjs 1.5 - 当字段 $pristine 时 $invalid

如果验证失败,如何停止表单提交[重复]

阻止用户提交表单

表单验证