AngularJS表单验证

143144次阅读
没有评论

共计 7843 个字符,预计需要花费 20 分钟才能阅读完成。

AngularJS表单验证

  • $viewValue

    $viewValue属性保存着更新视图所需的实际字符串。

  • $modelValue

    $modelValue由数据模型持有。$modelValue和$viewValue可能是不同的,取决于$parser流水线是否对其进行了操作。

  • $parsers

    $parsers的值是一个由函数组成的数组,当用户同控制器进行交互,并且ngModelController中的$setViewValue()方法被调用时,其中的函数在当用户同控制器进行交互,并且ngModelController中的$setViewValue()方法被调会以流水线的形式被逐一调用。ngModel从DOM中读取的值会被传入$parsers中的函数,并依次被其中的解析器处理。这是为了对值进行处理和修饰。

备注:ngModel.$setViewValue()函数用于设置作用域中的视图值。

ngModel.$set ViewValue()函数可以接受一个参数。

value(字符串):value参数是我们想要赋值给ngModel实例的实际值。

这个方法会更新控制器上本地的$viewValue,然后将值传递给每一个$parser函数(包括验证器)。当值被解析,且$parser流水线中所有的函数都调用完成后,值会被赋给$modelValue属性,并且传递给指令中ng-model属性提供的表达式。最后,所有步骤都完成后,$viewChangeListeners中 所有的监听器都会被调用。注意,单独调用$setViewValue()不会唤起一个新的digest循环,因此如果想更新指令,需要在设 置$viewValue后手动触发digest。$setViewValue()方法适合于在自定义指令中监听自定义事件(比如使用具有回调函数的 jQuery插件),我们会希望在回调时设置$viewValue并执行digest循环。

  • $formatters

    $formatters的值是一个由函数组成的数组,其中的函数会以流水线的形式在数据模型的值发生变化时被逐一调用。它和$parser流水线互不影响,用来对值进行格式化和转换,以便在绑定了这个值的控件中显示。

  • $viewChangeListeners

    $viewChangeListeners的值是一个由函数组成的数组,其中的函数会以流水线的形式在视图中的值发生变化时被逐一调用。通 过$viewChangeListeners,可以在无需使用$watch的情况下实现类似的行为。由于返回值会被忽略,因此这些函数不需要返回值。

  • $error

    $error对象中保存着没有通过验证的验证器名称以及对应的错误信息。

  • $pristine

    $pristine的值是布尔型的,可以告诉我们用户是否对控件进行了修改。

  • $dirty

    $dirty的值和$pristine相反,可以告诉我们用户是否和控件进行过交互。

  • $valid

    $valid值可以告诉我们当前的控件中是否有错误。当有错误时值为false,没有错误时值为true。

  • $invalid

    $invalid值可以告诉我们当前控件中是否存在至少一个错误,它的值和$valid相反。

See the Pen XmXLqz by iTattoo (@ZhouYanlang) on CodePen.

ngMessages的基本知识

而不是依赖复杂的错误消息处理使用ng-if表达式,让我们使用 ngMessages指令 。 首先,让我们来 包括 ngMessages进我们的应用程序,把ngMessages模块作为我们的应用程序模块 依赖

<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-messages.js"></script>
<script type="text/javascript">
  angular.module('myApp', ['ngMessages']);
</script>

现在我们可以重建我们的电子邮件形式的例子。 让我们剔除ng-If消息和包装在一个div元素的一切 ngMessages 指令和每个消息使用 ngMessage 指令。

<form name="userForm">
  <div class="field">
    <label for="emailAddress">Enter your email address:</label>
    <input type="email" name="emailAddress" ng-model="data.email" required />

    <div ng-messages="userForm.emailAddress.$error">
      <div ng-message="required">
        You forgot to enter your email address...
      </div>
      <div ng-message="email">
        You did not enter your email address correctly...
      </div>
    </div>
  </div>
  <input type="submit" />
</form>

这就是我们需要的所有代码!下面这种也是等价的!

<form name="userForm">
    <div class="field">
        <label for="emailAddress">Enter your email address:</label>
        <input type="email" name="emailAddress" ng-model="data.email" required/>

        <!-- this stuff is WAY too complex -->
        <div ng-if="userForm.emailAddress.$error.required" class="error">
            You forgot to enter your email address...
        </div>
        <div ng-if="!userForm.emailAddress.$error.required &&
                 userForm.emailAddress.$error.email" class="error">
            You did not enter your email address correctly...
        </div>
    </div>

    <input type="submit"/>
</form>

 

NgMessage究竟是如何工作的呢?

外部指令(ng-messages)监听 userForm.emailAddress。$error 对象(它包含一个键/值的所有错误出现在电子邮件地址列表模型)。 随着$error 对象状态的变化然后ng-messages指令将检查其内容的内部指令(ng-message指令)和选择 第一个 指令元素(在本例中所需的信息)。 根据上面的例子,如果$error 对象 required property,这是真的,那么将显示所需的信息。 如果不是下ng-message指令将检查(在这种情况下,电子邮件中),然后将显示如果错误存在。 因此,消息的顺序是优先的模板代码中而不是在控制器。

让我们扩展验证范围和最小长度和最大长度验证添加到我们的电子邮件输入元素。 现在我们如何结构消息代码吗?

<form name="userForm">
  <div class="field">
    <label for="emailAddress">Enter your email address:</label>
    <input type="email"
           name="emailAddress"
           ng-model="data.email"
           ng-minlength="5"
           ng-maxlength="30"
           required />

    <div ng-messages="userForm.emailAddress.$error">
      <!-- the required message is displayed first... -->
      <div ng-message="required">You forgot to enter your email address...</div>

      <!-- then, incase the message is too short, show the message right after -->
      <div ng-message="minlength">Your email address is too short...</div>

      <!-- of if is too long then let us know -->
      <div ng-message="maxlength">Your email address is too long...</div>

      <!-- otherwise let us know if the email itself is invalid -->
      <div ng-message="email">You did not enter your email address correctly...</div>
    </div>
  </div>

  <input type="submit" />
</form>

这种直观的方式显示什么错误出现时,都是由任何首先出现在DOM。 而不是依靠ng-If消息设置复杂的布尔表达式,排列ngMessages内在ng-message DOM元素的顺序,然后采取相应行动。 但是如果我们想显示所有信息,而不是仅仅一次? 这可以通过添加完成 ng-messages-multiple 属性ng-messages容器。

<!-- now everthing will show up whenever the errors are met -->
<div ng-messages="userForm.emailAddress.$error" ng-messages-multiple>
  <div ng-message="required">...</div>
  <div ng-message="minlength">...</div>
  <div ng-message="maxlength">...</div>
  <div ng-message="email">...</div>
</div>

同时,请记住,我们可以使用元素指示而不是attribtutes…

<!-- now everthing will show up whenever the errors are met -->
<ng-messages for="userForm.emailAddress.$error" multiple>
  <ng-message when="required">...</ng-message>
  <ng-message when="minlength">...</ng-message>
  <ng-message when="maxlength">...</ng-message>
  <ng-message when="email">...</ng-message>
</ng-messages>

这是比使用一系列ngIf表达式。 但我们仍然依赖于一个表达式是严格绑定到一个特定的模型形式。 我们怎么可能重用这些消息?

<!-- remote file: error-messages.html -->
<div ng-message="required">You left the field blank...</div>
<div ng-message="minlength">Your field is too short</div>
<div ng-message="maxlength">Your field is too long</div>
<div ng-message="email">Your field has an invalid email address</div>

现在让我们创建我们的形式,利用模板. .

<form name="userForm">
  <div class="field">
    <label for="emailAddress">Enter your email address:</label>
    <input type="email"
      name="emailAddress"
      ng-model="data.email"
      ng-minlength="5"
      ng-maxlength="30"
      required />
    <div ng-messages="userForm.emailAddress.$error"
    ng-messages-include="error-messages.html"></div>
  </div>
</form>

好了好了。 现在我们可以重用 错误消息 模板为基础为我们的错误消息的其他输入模型(输入元素)在我们的形式。 

<div ng-messages="userForm.emailAddress.$error"
     ng-messages-include="error-messages">
  <!-- only the required error message is replaced. The other ones are still there... -->
  <div ng-message="required">You did not enter an email address</div>
</div>

消息的顺序仍然是相同的(与所需消息出现第一),但而不是一般的,像机器人所需的消息出现,消息中定义ng-messages指令将被使用。 通过这种方式我们可以选择哪些信息重用和哪些覆盖。

自定义验证和错误消息

定制确认器可以创建通过创建一个指令,包括ngModel控制器,然后添加一个验证 美元的解析器 数组( 美元格式器 数组也可以使用,但美元更适合验证解析器)。 让我们创建一个验证器会检查我们的电子邮件地址可在我们的数据库通过一个API调用。

视图代码

myApp.directive('recordAvailabilityValidator',['$http', function($http) {
  return {
    require : 'ngModel',
    link : function(scope, element, attrs, ngModel) {
      var apiUrl = attrs.recordAvailabilityValidator;

      function setAsLoading(bool) {
        ngModel.$setValidity('recordLoading', !bool); 
      }

      function setAsAvailable(bool) {
        ngModel.$setValidity('recordAvailable', bool); 
      }

      ngModel.$parsers.push(function(value) {
        if(!value || value.length == 0) return;

        setAsLoading(true);
        setAsAvailable(false);

        $http.get(apiUrl, { v : value })
          .success(function() {
            setAsLoading(false);
            setAsAvailable(true);
          })
          .error(function() {
            setAsLoading(false);
            setAsAvailable(false);
          });

        return value;
      })
    }
  }
}]);
<form name="userForm">
  <div class="field">
    <label for="emailAddress">Enter your email address:</label>
    <input type="email"
           name="emailAddress"
           ng-model="data.email"
           ng-minlength="5"
           ng-maxlength="30"
           record-availability-validator="/api/emails.json"
           required />

    <div ng-messages="userForm.emailAddress.$error" id="error-messages.html">
      <div ng-message="recordLoading">Checking database...</div>
      <div ng-message="recordTaken">The email address is already in use...</div>
    </div>
  </div>

  <input type="submit" />
</form>

我们的验证器是漂亮的和可重用的。 我们可以用它来检查电子邮件地址是否可用等其他事情,我们甚至可以用它验证用户名或用户ID值的唯一性。 因为我们使用了 ngModel.$setValidity。 方法提供了一个错误的名字,错误将出现在模型的错误对象时出现的错误。 因此,显示两条消息(加载错误和可用性错误)这只是一种放置ngMessage指示容器的内部消息。

<!-- now everthing will show up whenever the errors are met -->
<div ng-messages="userForm.emailAddress.$error" ng-messages-multiple>
  <div ng-message="required">...</div>
  <div ng-message="minlength">...</div>
  <div ng-message="maxlength">...</div>
  <div ng-message="email">...</div>
  <div ng-message="recordLoading">Checking database...</div>
  <div ng-message="recordTaken">The email address is already in use...</div>
</div>

现在recordLoading和recordTaken消息显示当他们被评估只要邮件地址模型中的变化。 现在上面的验证程序代码并不完美,它不检查存在的其他错误也不取消先前的XHR请求。 但这是一种锻炼,是完美的;你)

如果你想看到一个这样的例子,请查看演示应用程序,输入一个 用户名的值

See the Pen YyqzpO by iTattoo (@ZhouYanlang) on CodePen.

动画的钩子

自从ngMessages ngMessage指令使用 美元的动画 服务管理的DOM操作,动画可以放置在错误消息交换,当没有错误消息显示。 这些钩子可以允许一些有趣的动画被触发时用户在屏幕上展示了一个错误。

动画与< ng-messages >

外ng-messages指令添加 ng-active CSS类的容器元素显示当有一个或多个错误。 否则删除,并添加CSS类 ng-inactive CSS类。

动画与< ng-message >

内部ng-message指令添加插入和删除自己在触发 输入 离开 启动动画事件。 点击这里了解动画在AngularJS

正文完
 0
Chou Neil
版权声明:本站原创文章,由 Chou Neil 于2015-09-16发表,共计7843字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。