【问题标题】:How do you force form validation for all fields on submit? [duplicate]您如何强制提交时对所有字段进行表单验证? [复制]
【发布时间】:2014-05-25 23:20:12
【问题描述】:

我需要能够验证某些字段,即使它们从未被用户触摸过。有些字段是必填的,但至少就我目前的经验而言,必填字段不会在 submit 时失效:它只会在 blur 时失效。因此,如果用户从未真正接触过某个字段(或任何字段,就此而言)并点击提交,则表单将成功验证并提交,从而导致服务器端验证错误。

关于 AngularJS 表单验证的问题:如何强制整个表单在提交时进行验证,无论用户是否实际触摸了任何表单字段?

我有一堆表格,在大多数表格上都有几个必填字段,以及具有最小/最大和最大长度要求的字段。如果我只是构建一个 AngularJS 表单,应用像 ng-required 这样的指令,然后点击提交,表单总是提交。没有什么能阻止它。

如果必填字段为空,我需要我的表单不提交,无论用户是否实际触摸它们并离开(这是触发模糊事件的唯一方式,因此也是验证这些字段的唯一方式。 )

在这里使用“禁用”提交按钮的方法对我来说是不可接受的。

我参考过的资源:

  • Processing Forms in AngularJS
    • 问题:if (form.$invalid) return; 成语不起作用。我遇到错误“TypeError: Cannot read property '$valid' of undefined”
  • Form Validation: The AngularJS Way
    • 虽然我认为这是一种有趣的方法,但我们的客户不希望成千上万的小型 ajax 请求对其数据库服务器执行内联(即 onblur)验证。因此,使用unique 指令验证用户名唯一性等方法对我们来说不是一个选择。

作为参考,这是我当前在控制器中的提交功能:

表格:

<div ng-switch on="state" ng-controller="OwnerCtrl">

<!-- A whole bunch of other layout and informational junk -->

    <form name="ownerForm" novalidate ng-submit="submit(ownerForm)">
        <div class="row-fluid">
            <div class="span3 control-group" ng-class="{error: ownerForm.FirstName.$dirty && ownerForm.FirstName.$invalid }">
                <label class="control-label" for="FirstName" ng-class="">First Name</label>

                <div class="controls">
                    <input class="input-block-level" data-val="true" data-val-required="First Name is required"
                               id="FirstName" name="FirstName" placeholder="First Name" type="text" ng-required ng-model="owner.firstName"/>
            </div>
        </div>

        <!-- A BUNCH of other form controls here -->

        <div class="row-fluid">
            <div class="span3">
                <button class="btn btn-info" ng-click="back()">
                    <span ng-hide="transitionBack"><i class="icon-chevron-left icon-white"></i><i class="icon-chevron-left icon-white"></i>&nbsp;Back</span>
                    <span ng-show="transitionBack">Loading...</span>
                </button>
            </div>
            <div class="span3">
                <button class="btn btn-primary" type="submit">
                    <span ng-hide="transitionForward"></span>Continue<i class="icon-chevron-right icon-white"></i><i class="icon-chevron-right icon-white"></i></span>
                    <span ng-show="transitionForward">Loading...</span>
                </button>
            </div>
        </div>
    </form>
<div>

控制器:

var owner = angular.module("Owner", []);

owner.controller("OwnerCtrl", ["$scope", "$location", "$log", function($scope, $location, $log) {

    $scope.owner = {
        firstName: "",
        lastName: "",
        middleInitial: "",
        birthDate: null,
        ssn: "",
        phoneNumber: ""
    };

    $scope.formSubmitted = false;

    $scope.submit = function(form) {
        // Found this on a blog somewhere, just an attempt to FORCE form validation even
        // on elements that have never been touched by the uyser
        for (var field in form) {
            // look at each form input with a name attribute set
            // checking if it is pristine and not a '$' special field
            if (field[0] != '$' && form[field].$pristine) {
                form[field].$setViewValue(
                    form[field].$modelValue
                );
            }
        }

        $scope.formSubmitted = true;

        if (form.$invalid)
            return;
    }
}

我已经从示例中删除了其他不必要的 html 和 js 部分,以保持简洁。这是对手头的问题很重要的唯一代码。

作为旁注。我目前正在传递表单,而不是使用$scope.ownerForm.$valid。尽管我确实为我的表单命名,$scope.ownerForm 不起作用。表单属性是未定义的,但似乎只有当我尝试访问它的 $valid 或 $invalid 属性时。具有讽刺意味的是,$scope.ownerForm[field] 确实有效(最初,在我开始传入表单对象之前)。只有当我访问 $valid/$invalid 属性时,它似乎才失败。


更新:

所以,我的问题似乎比提交时验证表单更严重。它实际上看起来好像我的表格没有验证,句号。我刚刚完成了我的整个表单,用所有无效数据填写了它(太长的字符串,数字字段中的非数字数据,并且将必填字段留空。Angular 应该在它们模糊时立即验证这些字段,就我而言了解。没有一个字段无效。调试我的提交功能,该表单当前标记为有效。此外,我使用 Chrome 的开发工具检查了每个字段,所有字段都标记为脏,并且 valid,不无效。

似乎 required/ng-required 并且所有其他表单验证属性都被忽略了......但是在 Chrome 的开发工具中,我可以看到附加到每个添加到表单对象的输入属性的函数。例如,在所有必填字段上,我可以看到一个显然旨在验证该要求的函数。 $parsers 数组中也有一些东西。

我完全感到困惑。 为什么我的表单验证不起作用?

【问题讨论】:

  • 这不应该被关闭。这是一个不同的问题

标签: forms angularjs validation


【解决方案1】:

如果您不想使用ng-disabled 方法,我会使用ng-submit 方法;您可以在提交时启动自定义验证功能,“手动”检查字段是否有错误。比如:

// inside the controller
$scope.onSubmit = function($event) {
  // check for errors; if wrong return/preventDefault/doTheRightThing
  // else continue
};
//...

和 HTML:

<form ng-submit="onSubmit">
  <!-- form fields -->
</form>

【讨论】:

  • 我已经尝试过这种方法。尽管在我的表单输入元素上有requiredng-required(以及其他),但没有进行必要的验证。我什至尝试强制验证(我将使用提交函数实现更新我的问题为清楚起见),即使这样我的表单实际上仍然没有正确失效。
【解决方案2】:

你错了。表单元素和表单本身的验证状态是不断更新的。每次用户在元素中输入内容,或者每次底层模型发生变化时,元素和表单的$invalid/$valid 属性都会更新。

所以,在你的提交方法中,你只需要检查表单的$valid 属性是真还是假,并采取相应的行动。

如果您收到“无法读取未定义的属性 '$valid'”,则表示您没有为表单命名,或者您在控制器中使用了不正确的名称。向我们展示您的代码以帮助我们诊断问题。

工作演示:http://plnkr.co/edit/ImnC4d2WXNdsDqwNlTUa?p=preview

【讨论】:

  • 如果模型没有改变呢?我们正在更新我们的流程,数据库中的一些源数据在新规则下可能无效。用户登录,表单填充了他们当前的数据,他们点击“下一步”......他们继续,当表单验证应该发现错误并阻止它们继续时。模型永远不会改变,用户甚至可能永远不会触摸表单(按钮除外)......在这种情况下不会发生验证(至少,它不适合我。)
  • 我们可以让问题变得更简单。我加载我的表格。我不碰它,没有预加载数据,但没有碰表单字段,也没有更改模型。我单击“下一步”......并且表单验证没有启动。我的问题是AngularJS表单验证是事件驱动的。除非有什么改变,否则它不会发生。即使我在问题中的代码中的小循环似乎也没有触发必填字段,无论如何都应该验证,实际上被标记为无效。它们被标记为脏,但不是无效的。这对我来说似乎很错误。应验证必填字段...
  • ...无论字段是否模糊或模型是否更改。这是我正在经历的行为。我应该经历其他事情吗?或者这就是 Angular 的工作原理?
  • 点击我回答中的链接。按提交按钮。看看显示的内容:表格无效。尽管您还没有触及任何输入字段。验证是事件驱动的,显示初始值已经是设置表单有效性的事件。关于您的代码: ng-required 需要一个布尔值。尝试编写一个重现问题的 plunkr,就像我编写了一个显示验证工作正常的 plunkr 一样。
  • @JBL 我第一次检查了你的 plunker。我尝试过使用各种方法来满足要求。我刚刚使用了requiredng-requiredng-required="true",都无济于事。 ng-maxlength="40" 也会出现同样的问题,它位于我的其他表单字段中。在我的项目中似乎有些东西干扰了 AngularJS 的表单验证,所以我想我只需要在一堆针头里四处寻找干草……蒙住眼睛。
猜你喜欢
  • 2021-09-13
  • 2021-10-29
  • 2019-07-14
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-08
相关资源
最近更新 更多