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


155

我正在使用带有一些客户端输入验证的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。



我们可以在没有form标签的情况下使用它吗,仍然form.valid可以在ng-click上工作!
Rizwan Patel

Answers:


329

你可以做:

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

无需控制器检查。


8
这应该是公认的答案。无需检查控制器中的任何内容
Howie 2014年

10
我不同意“无需进行控制器检查”。如果我们在提交功能中进行了其他验证检查该怎么办。
SlaterCodes

6
在指令中执行其他验证。使用$ setValidity更新验证。
TMB

@ b1tsh1ft最好始终知道验证的当前状态,而不要在提交时弄清楚。这就是角度验证的全部要点。当示波器不知道无效状态时,您将无法获得任何视觉上的指示。
凯文·比尔,2015年

1
我已经尝试过这种方法,但是似乎可以同时评估这两种方法(即,在&&我尝试将值作为提交的一部分传递并确认值本身为“ false” 后,它不会使布尔值短路)
Archimedes Trajano

67

将提交按钮更改为:

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

1
好答案。你摇滚!
Harsha.Vaswani'3

24
如果在输入字段具有焦点的情况下按Enter,您仍然可以提交表单!
fabsenet,2015年

2
@Red:请参见上面的评论。
AndreiRînea2015年

虽然禁用按钮通常是解决此问题的最佳方法,但这不是OP所要求的。
平焊

1
结合使用此技术为用户提供视觉反馈以及@Yashua答案,以防止表单提交是完美的。谢谢!
tkarls

43

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

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

这将使表格在controller方法中可用:

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

我遇到过同样的问题。但是,使用您的方法是可行的。
Panda4Man 2014年

这比“接受的答案”稍好一点,因为form。$ valid检查是在JS中完成的,而不是在HTML中完成的。
cellepo '17

但是,我认为您不需要传递loginForm来提交函数:我认为$ scope.loginform应该在JS中可用(至少对我而言),因此您可以将form。$ valid替换为$ scope.loginform 。$有效。
cellepo

13

您的表单会自动作为对象放入$ 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


4
如果使用“作为控制器”表示法而不是$ scope,将如何访问表单?
masimplo

@masimakopoulos:您可以简单地使用if(this.loginform.$invalid)..来代替,但是在HTML中,您必须为表单指定名称<form name="ctrl.loginform" ..。并假设您<div ng-controller="controller as ctrl"..在控制器中使用as语法。感谢@JoshCaroll
Bart

13

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方法中进行检查?这意味着您必须检查输入是否满足标记(通过angular)和js代码中的所有条件。我认为,当输入无效时,angular不应调用onsubmit。请参阅benlesh.com/2012/11/angular-js-form-validation.html,说“只有在整个表单有效之前,才能调用ng-submit”
Runar Halse 2013年

如果表单有效,您也可以禁用该按钮以不允许提交。您也可以使用ng-submit形式。如果angular不处理表单验证,那么event.preventDefault()应该停止表单提交。
TheHippo

@RunarHalse确实有必要进行检查。我同意你的看法,不应该这样。在您链接的示例中未调用onsubmit方法的原因是因为该示例未设置novalidate。浏览器阻止事件引发,而不是Angular。这是他的示例(带有nobalidate):plnkr.co/edit/R0C8XA ? p= preview。注意表单提交。
davidmdem

恰好是我想要的东西,一种使用角度阻止表单提交的方法
setebos

3

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

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

2

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

我当时有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>

无论我尝试了多少,一旦表格有效,请按Enter键,将调用“清除表格”按钮,清除整个表格。

作为解决方法,

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

<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属性来停止按回车提交
Kieran

1

我知道这是一个老话题,但我想我也会有所作为。我的解决方案类似于已经标记为答案的帖子。一些内联JavaScript检查可以解决问题。

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

1
如果在输入字段具有焦点的情况下按Enter,您仍然可以提交表单!
Yevgeniy Afanasyev

0

我知道已经很晚了并且得到了答复,但是我想分享我做的整洁的东西。我创建了一个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">
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.