AngularJS 表单提交验证:$dirty、$valid 和 $invalid

⚡ 智能摘要

AngularJS 中的表单验证会在数据发送到服务器之前检查表单中输入的数据是否正确完整。本文将介绍四种方法,从普通的 HTML5 属性、作用域属性到自动验证模块。

  • 🧩 HTML5属性: 必填属性以及电子邮件、密码和数字输入类型可实现浏览器原生检查,无需脚本。
  • 🔍 状态属性: AngularJS 会在命名表单中的每个命名控件上公开 $dirty、$pristine、$valid 和 $invalid。
  • 🏷️ 命名要求: 表单和每个控件都需要一个 name 属性,因为验证状态是通过 formName.controlName 来获取的。
  • 🚫 禁止弹出式窗口: 在表单中添加 novalidate 属性可以阻止浏览器拦截提交操作,以便 AngularJS 可以处理它。
  • 💬 消息显示: ngMessages 模块取代了堆叠的 ng-show 指令,并按优先级顺序一次显示一个错误。
  • ⚙️ 自动验证: jcs-autoValidate 模块无需任何自定义标记即可为每个控件生成错误消息。
  • 🔘 提交反馈: Ladda 按钮会在提交过程中应用旋转图标,向用户显示进度。

AngularJS 中的表单验证

表格验证 在 AngularJS 中,验证是确保表单中输入的数据正确完整过程。用户提交表单后,在将数据发送到服务器之前,会先进行验证。验证过程旨在最大程度地确保输入字段已正确填写。

举个实际例子,假设某个网站要求用户填写注册表单才能获得完整访问权限。注册页面会有用户名、密码、邮箱地址等输入框。

例如,电子邮件地址必须始终采用以下格式: 用户名@站点.域名如果有人只输入用户名,验证应该失败。验证会在将详细信息发送到服务器进行进一步处理之前执行这些基本检查。

⚠️ 版本说明: AngularJS(1.x 分支)已于 2021 年 12 月 31 日停止维护,不再接收任何安全补丁。以下方法仍然适用于旧版应用程序;现代 Angular 使用模板驱动或响应式表单来处理相同的任务。

使用 HTML5 进行表单验证

表单验证是指在将网页表单发送到服务器之前,预先验证用户输入的信息。客户端验证更可取,因为它比往返服务器后重新提交表单的开销要小得多。

下面的示例展示了一个简单的注册表单,用户可以在其中输入用户名、密码、电子邮件地址和年龄。该表单包含验证控件,以确保信息输入正确。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
</head>
<body ng-app="sampleApp">
<h1>Guru99 Global Event</h1>

<form>
    Enter your user name:
    <input type="text" name="name" required><br><br>

    Enter your password:
    <input type="password" name="password"><br><br>

    Enter your email:
    <input type="email" name="email"><br><br>

    Enter your age:
    <input type="number" name="age"><br><br>

    <input type="submit" value="Submit">
</form>
</body>
</html>

⚠️ 本页面所有信息均已更正。 原件声明 chrset="UTF 8"这既不是有效的属性,也不是有效的编码,并且导致 AngularJS 加载了三次—— angular-route.js 首先,这会抛出异常,因为路由模块注册的框架尚未加载;然后 angular.min.jsangular.js他们两次使用了同一个图书馆。他们还提取了 bootstrap.css 通过 <script> 标签,因此从未应用任何样式。现在每个列表都加载一个库(版本 1.8.3),并正确链接样式表。布局内边距由重复元素构成。 &nbsp; 实体已被移除。

Code 说明

  1. 对于文本输入类型, required 该属性表示表单提交时文本框不能为空。
  2. 下一个输入类型是密码。由于该类型被标记为密码,因此字段中输入的文本将被屏蔽。
  3. 由于输入类型指定为电子邮件,因此框中的文本必须与模式匹配。 名称@站点.域名.
  4. 当输入类型标记为数字时,该字段根本不接受从键盘输入的字符。

输出

要查看验证效果,请点击“提交”按钮,无需输入任何内容。

弹出窗口提示需要填写该字段,因此标记为必填的控件会在字段为空时阻止提交。

在密码控件中输入值时,会显示“*”符号来遮盖字符。

输入格式错误的电子邮件地址并点击“提交”后,会弹出窗口要求输入@符号。此外,在年龄字段中输入的字符不会显示,因为该字段只接受数字。

浏览器弹出窗口设置快捷,但其文字和样式无法更改。这时,AngularJS 的验证属性就派上了用场。

使用 $dirty、$valid、$invalid、$pristine 进行表单验证

AngularJS 它提供了用于验证的自身属性。以下属性在每个命名控件上都公开:

  • $脏 – 用户已经与控件交互
  • $有效 – 字段内容有效
  • $无效 – 字段内容无效
  • $原始 – 用户尚未与控件进行交互

以下是执行 AngularJS 验证的步骤。

步骤1) 使用 novalidate 声明表单时添加此属性。这会告诉浏览器验证将由 AngularJS 处理。

步骤2) 请确保表单已定义名称,因为该名称用于进入验证状态。

步骤3) 确保每个控件也都有 name 出于同样的原因,属性也需要进行设置。没有名称的控件永远不会在表单上注册。

步骤4) 使用 吴秀 指示检查 $dirty、$invalid 和 $valid 属性。

以下示例包含一个文本字段,供用户输入主题名称。如果该字段为空,则会触发验证错误并显示错误信息。

<form ng-app="DemoApp" ng-controller="DemoController"
      name="myForm" novalidate>
    <p>Topic Name:<br>
        <input type="text" name="user" ng-model="user" required>

        <span style="color:red"
              ng-show="myForm.user.$dirty && myForm.user.$invalid">
            <span ng-show="myForm.user.$error.required">Username is required</span>
        </span>
    </p>
    <p>
        <input type="submit" ng-disabled="myForm.$invalid">
    </p>
</form>

<script>
    var app = angular.module("DemoApp", []);

    app.controller("DemoController", function($scope) {
        // Seed the textbox so the form starts in a valid state
        $scope.user = "AngularJS";
    });
</script>

⚠️ 已修正两处逻辑错误。 原先禁用了该按钮 ng-disabled="myForm.user.$dirty && myForm.user.$invalid"。 因为 $dirty 在用户触摸该字段之前,该值为假;按钮一直处于显示状态。 启用 在未经修改的空白表单上,正是它要阻止的情况; myForm.$invalid 两者都涵盖了。原版还将默认值封装在内。 $scope.Display = function () { $scope.user = 'Angular'; }这是一个从未被调用过的函数,因此尽管文本框显示“AngularJS”,但文本框打开时却是空的。现在直接赋值,值包含在周围文本的引号中。

Code 说明

  1. 表单被命名为“myForm”。这是为了能够访问其控件进行验证而必须的。
  2. novalidate 该属性会阻止浏览器进行验证,以便 AngularJS 可以代替浏览器进行验证。
  3. ng-show 指令会检查“$dirty”和“$invalid”属性。如果文本框已被修改,则 $dirty 为 true;如果文本框的值为空,则 $invalid 为 true。当这两个属性都为 true 时,将显示带有红色文本的 span 元素。
  4. 嵌套检查会读取“$error.required”属性,当必填控件没有值时,该属性为真,并显示“用户名是必填项”。
  5. 提交按钮已禁用 ng-disabled 当整个表单无效时。
  6. 控制器将初始文本框值设置为“AngularJS”,因此表单以有效状态打开,并且在删除文本时更容易观察验证过程。

输出

表单首次显示时,文本框中会显示“AngularJS”,并且提交按钮处于启用状态。删除文本后,会显示错误信息,并且按钮会变为禁用状态。

上面的截图显示了两件事:

  • 提交按钮已禁用
  • “主题”文本框中没有主题名称,因此显示错误消息“需要用户名”。

如何使用 ngMessages 显示验证错误

上述模式可行,但无法扩展。一个包含四个约束的字段需要四个嵌套的约束。 ng-show 跨度,当多个跨度同时失效时,所有消息会同时出现。 ngMessages AngularJS 团队单独发布的模块解决了这两个问题:它一次显示一条消息,并按照消息的编写顺序显示。

加载模块并将其添加为依赖项。

<script src="https://code.angularjs.org/1.8.3/angular-messages.js"></script>
<script>
    angular.module("DemoApp", ["ngMessages"]);
</script>

这样一来,标记就变成了一系列规则,而不是一堆条件。

<input type="text" name="user" ng-model="user"
       required ng-minlength="4" ng-maxlength="20">

<div style="color:red" ng-messages="myForm.user.$error"
     ng-if="myForm.user.$dirty">
    <div ng-message="required">A topic name is required</div>
    <div ng-message="minlength">Use at least 4 characters</div>
    <div ng-message="maxlength">Use no more than 20 characters</div>
</div>

三个细节使得它在实践中表现良好。 ng-messages 属性指向控件的 $error 它返回的是一个对象而不是一个布尔值,因此无需重复条件。只需匹配第一个对象即可。 ng-message 渲染结果显示,即使字段为空,也会报告它是必填项,而不会因为字段长度不足而发出警告。添加 ng-messages-multiple 当确实需要列出所有失败案例时,这种做法就会发生逆转。

饺子皮ping 街区 ng-if="myForm.user.$dirty" 保持表单静默,直到用户实际输入内容。替换 $touched HPMC胶囊 $dirty 进一步延迟显示消息,直到焦点离开该字段,这在冗长的注册表单中通常是更友好的选择。

一个警告: ngMessages 由于它作为单独的文件发送,因此忘记脚本标签或模块依赖项会导致代码块完全不渲染任何内容,并且控制台不会出现任何错误来解释这种情况。

手写信息虽然精确,但很重复。下一节将介绍一个可以自动生成信息的模块。

使用 AngularJS Auto Validate 进行表单验证

AngularJS 可以自动验证表单上的所有控件,无需编写自定义验证代码或错误消息。这是通过引入名为“jcs-autoValidate”的社区模块实现的。

有了这个模块,就不需要特殊的代码来运行验证或显示消息;一切都在 jcs-autoValidate 内部处理。

下面的示例是一个简单的表单,其中包含一个必填文本框。如果该文本框未填写,则会显示错误消息。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
    <script src="lib/jcs-auto-validate.min.js"></script>
</head>
<body>
<h1>Guru99 Event</h1>

<div ng-app="DemoApp">
    <form name="myForm" novalidate>
        <div class="form-group">
            <label for="user">Topic Name:</label>
            <input class="form-control" type="text"
                   id="user" name="user" ng-model="user" required>
        </div>
        <div class="form-group">
            <input type="submit">
        </div>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', ['jcs-autoValidate']);
</script>
</body>
</html>

⚠️更正: 原图将对照组确定为 id="user" 仅此而已。jcs-autoValidate 通过表单访问控件,因此 name 该属性是必填项,缺少该属性则不会显示消息。原始版本还加载了两个不同的 AngularJS 版本,分别是 1.6.4 和 1.6.4。 Google CDN 与 1.6.9 版本一起,但从未链接 Bootstrap 即使这个例子取决于它的 form-groupform-control 用于定位错误文本的类。

💡注意: jcs-autoValidate 是一个社区项目,目前已停止维护。它仍然可以在现有的 AngularJS 应用程序中使用,但内置的自动验证功能已不再可用。 ngMessages 对于任何新事物,前面提到的方法都是更安全的选择。

Code 说明

  1. 包含了所有自动验证功能的“jcs-auto-validate.js”脚本。
  2. 每个控件及其周围的 div 元素都放置在“form-group”类中,模块会将消息注入到该类中。
  3. 控件同时包含一个id和一个 name和 Bootstrap 提供 form-control 样式。
  4. “jcs-autoValidate”模块被列为AngularJS模块的依赖项。

输出

默认情况下,表单将完全按照编写的内容呈现。

提交空白表单后,会显示“此字段为必填项”的消息,该消息完全由 jcs-autoValidate 生成。表单验证通过后,剩下的问题是用户在提交表单时会看到什么。

用户对 Ladda 按钮的反馈

“Ladda”按钮是一个构建在……之上的框架 JavaScript 按下按钮时,按钮会产生视觉效果。

如果按钮被赋予“ladda”属性并被按下,则会显示旋转效果。此外,还有不同的数据样式可用于实现其他视觉效果。

下面的示例展示了一个带有提交按钮的简单表单。按下按钮后,表单上会出现旋转效果。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <link rel="stylesheet" href="lib/bootstrap.css">
    <script src="https://code.angularjs.org/1.8.3/angular.min.js"></script>
    <script src="lib/angular-ladda.min.js"></script>
</head>
<body>
<h1>Guru99 Event</h1>

<div ng-app="DemoApp" ng-controller="DemoController">
    <form name="myForm" novalidate ng-submit="submit()">
        <button class="btn btn-primary" type="submit"
                ladda="submitting" name="sbutton"
                data-style="expand-right">Submit</button>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', ['angular-ladda']);

    app.controller('DemoController', function($scope) {
        $scope.submitting = false;

        $scope.submit = function() {
            $scope.submitting = true;
        };
    });
</script>
</body>
</html>

⚠️更正: 原始加载 angular-ladda.jsangular-ladda.min.js 同时,它注册了同一个模块两次,并且又引入了两个 AngularJS 版本。它还列出了 jcs-autoValidate 作为本示例中从未使用的依赖项。此处加载了每个库的一个副本。

Code 说明

  1. “”提交”指令调用名为“submit”的函数,该函数会更改按钮的ladda属性。
  2. ladda 属性属于 Ladda 框架,用于添加旋转效果。它的值绑定到…… submitting 变量。
  3. data-style 属性是 Ladda 的另一个属性,用于选择不同的视觉效果。
  4. 要使框架正常工作,必须将“angular-ladda”模块添加到AngularJS应用程序中。
  5. submitting 变量初始化为 false,因此按钮启动时不会有旋转效果。
  6. 提交函数设置 submitting 设置为 true 即可应用该效果。在实际应用中,一旦服务器响应,该值就会重置为 false,否则按钮会一直旋转。

输出

表单首次显示时,提交按钮会以最简洁的形式显示。

当按钮被按下时, submitting 变量被设置为 true。该值会传递给按钮的“ladda”属性,从而产生旋转效果。

常见问题

当值发生变化时,`$dirty` 变为 true。当字段失去焦点时,`$touched` 变为 true。使用 `$touched` 可以延迟错误提示,直到用户继续操作,这样感觉更温和。ping.

添加带有正则表达式的 ng-pattern 指令,例如 ng-pattern=”/^[0-9]{6}$/”。然后,错误信息会以 $error.pattern 的形式显示出来,ngMessages 可以像报告任何内置约束一样报告该信息。

是的。AI 工具会读取标记并生成匹配的 required、ng-pattern 和 ngMessages 代码块。务必检查正则表达式,因为生成的电子邮件地址和电话号码模式经常会拒绝有效的输入。

AI 助手会快速检查三个常见原因:表单或控件缺少 name 属性、缺少 ng-model 以及 novalidate 未启用,导致浏览器首先拦截提交。

不。它确实能改善用户体验并减少往返次数,但任何人都可以使用开发者工具绕过它。浏览器中强制执行的每一条规则都必须在服务器端再次强制执行。

总结一下这篇文章: