zoukankan      html  css  js  c++  java
  • AngularJS开发指南6:AngularJS表单详解

    表单控件(input, select, textarea )是用来获取用户输入的。表单则是一组有联系的表单控件的集合。

    用户能通过表单和表单控件提供验证的服务,知道自己的输入是否合法。这样能让用户交互变得友好,因为用户能通过反馈来修正自己的错误。不过,虽然客户端的验证能够起到很大作用,但也很容易被绕过,所以不能完全依靠客户端验证。 要建立安全的应用,服务器端验证还是必不可少的。

    了解AngularJS双向绑定的关键在于了解ngModel指令。这个指令通过动态将model和view互相映射,来实现双向绑定。

    为了能美化表单和表单元素,ngModel指令会自动为元素添加以下css类:

    • ng-valid
    • ng-invalid
    • ng-pristine
    • ng-dirty

    一个表单就是一个FormController的实例,表单实例可以通过name属性选择性地公开到作用域中。同样的,一个表单控件也是一个NgModelController的实例,表单控件也能同样的被公开到作用域中。这意味视图能通过绑定的基本功能获取表单或者表单控件的状态。

    • 只有当表单发生改变时,重置按钮才会被显示出来。
    • 只有当表单有改变并且改变的值都是合法的,保存按钮才会被显示出来。
    • 能自定义user.email和user.agree的错误信息。

    举个例子:

    <!doctype html>
    <html ng-app>
      <head>
        <script src="http://code.angularjs.org/angular-1.0.2.min.js"></script>
        <script>
            function Controller($scope) {
            $scope.master= {};
            $scope.update = function(user) {
                $scope.master= angular.copy(user);
            };
            $scope.reset = function() {
                $scope.user = angular.copy($scope.master);
            };
            $scope.isUnchanged = function(user) {
                return angular.equals(user, $scope.master);
            };
            $scope.reset();
        }
        </script>
      </head>
      <body>
        <div ng-controller="Controller">
          <form name="form" class="css-form" novalidate>     //novalidate是用来屏蔽浏览器本身的验证功能的。
            Name:
              <input type="text" ng-model="user.name" name="uName" required /><br />    //required,此输入框必须有内容
            E-mail:
              <input type="email" ng-model="user.email" name="uEmail" required/><br />
            <div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:           //此div,如果form表中的name为uEmail的input元素中的内容违法或者是脏数据,那么就显示出来。
              <span ng-show="form.uEmail.$error.required">Tell us your email.</span>     //如果错误信息是由required引起的,就显示此span
              <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>    //如果错误信息是由里面的内容不合法引起的,就显示此span
            </div>
    
            Gender: <input type="radio" ng-model="user.gender" value="male" />male
            <input type="radio" ng-model="user.gender" value="female" />female<br />
    
            <input type="checkbox" ng-model="user.agree" name="userAgree" required />
            I agree: <input ng-show="user.agree" type="text" ng-model="user.agreeSign"
                      required /><br />
            <div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
    
            <button ng-click="reset()" ng-disabled="isUnchanged(user)">RESET</button>
            <button ng-click="update(user)" ng-disabled="form.$invalid || isUnchanged(user)">SAVE</button>  //如果整个form表单没有通过验证或者form表单中的内容没有发生改变,此按钮就不可点击
          </form>
        </div>
      </body>
    </html>

    AngularJS实现了大部分常见的html5表单输入元素(text, number, url, email, radio, checkbox),也实现了很多用于验证的指令(required, pattern, minlength, maxlength, min, max)。

    如果想要定义你自己的验证器的话,可以通过在你自己的指令中添加一个验证函数给ngModel的控制器来实现。要想获得控制器的引用,需要在指令中指定依赖,验证函数可以写在两个地方。

    • 模型到视图的更新中- 只要绑定的模型改变了,NgModelController#$formatters数组中的函数就会被轮流调用,所以每一个函数都有机会对数据进行格式化,当然你也可以通过NgModelController#$setValidity来改变表单的验证状态。

    • 视图到模型的更新中- 相同的,只要用户与表单交互了,NgModelController#$setViewValue就会被调用。 这次是NgModelController#$parsers数组中的函数会被依次调用,每个函数都有机会来改变值或者通过NgModelController#$setValidity来改变表单的验证状态。下面的例子,使用的是这个。

    举个例子:

    <!doctype html>
    <html ng-app="form-example1">
      <head>
        <script src="http://code.angularjs.org/angular-1.0.2.min.js"></script>
        <script>
              var app = angular.module('form-example1', []);
          var INTEGER_REGEXP = /^-?d+$/;   //或者以"-"(负)开头,或者没有负号,后面都是正整数,包括0
          app.directive('integer', function() {
             return {
                require: 'ngModel',    //依赖nogModel指令
                link: function(scope, elm, attrs, ctrl) {
                    ctrl.$parsers.unshift(function(viewValue) {      //ctrl可以调用ngModel指令中controller函数中定义的方法
                        if (INTEGER_REGEXP.test(viewValue)) {
                            ctrl.$setValidity('integer', true);
                            return viewValue;
                        } else {
                            ctrl.$setValidity('integer', false);
                            return undefined;
                        }
                    });
                }
             };
          });
          var FLOAT_REGEXP = /^-?d+((.|\,)d+)?$/;  //可以是正负,可以是整数,也可以是浮点数,浮点数可以用"."分开,也可以用","分开。
          app.directive('smartFloat', function() {
             return {
                require: 'ngModel',
                link: function(scope, elm, attrs, ctrl) {
                    ctrl.$parsers.unshift(function(viewValue) {
                        if (FLOAT_REGEXP.test(viewValue)) {
                            ctrl.$setValidity('float', true);
                            return parseFloat(viewValue.replace(',', '.'));
                        } else {
                            ctrl.$setValidity('float', false);
                            return undefined;
                        }
                    });
                }
             };
          });
        </script>
      </head>
      <body>
        <div ng-controller="Controller">
          <form name="form" class="css-form" novalidate>
            <div>
              Size (integer 0 - 10):
              <input type="number" ng-model="size" name="size" min="0" max="10" integer />{{size}}<br />   //integer,自定义指令
              <span ng-show="form.size.$error.integer">This is not valid integer!</span>
              <span ng-show="form.size.$error.min || form.size.$error.max">The value must be in range 0 to 10!</span>
            </div>
    
            <div>
              Length (float):
              <input type="text" ng-model="length" name="length" smart-float />{{length}}<br />   //smart-float,自定义指令
              <span ng-show="form.length.$error.float">This is not a valid float number!</span>
            </div>
          </form>
        </div>
      </body>
    </html>

    上面的例子中,我们创建了两个指令。

    • 第一个指令是要验证输入的是否是整数。例如,1.23就不符合验证的值,因为它包含了分数部分。

    • 第二个指令是要验证输入的是否是“智能浮点(smart-float)”。它能把"1.2"或者"1,2"都转化为合法的浮点数"1.2"。注意,这里我们不能使用input元素的type="number",因为支持HTML5的浏览器不允许用户输入像"1,2"这样的非法值。

    AngularJS已经实现了所有基本的HTML表单控件(input,select,textarea),对于大部分情况应该已经够了。但是,你还是可以通过写指令来实现你自己的表单控件。

    要和ngModel指令协同工作实现自定义控件,并且实现双向绑定的话,需要:

    • 实现render方法。这个方法负责在数据模型变化时,把变化的值传递给NgModelController#$formatters后,用来在view上渲染新的数据。
    • 在用户与控件交互并且模型需要被更新时,调用$setViewValue方法。这通常是在DOM的监听事件中完成的。

    下面的例子演示了如何添加一个“内容可编辑”的数据双向绑定的元素。

    <!doctype html>
    <html ng-app="form-example2">
      <head>
        <script src="http://code.angularjs.org/angular-1.0.2.min.js"></script>
        <script>
           angular.module('form-example2', []).directive('contenteditable', function() {   //自定义指令contenteditable
            return {
                require: 'ngModel',
                link: function(scope, elm, attrs, ctrl) {
                    // view -> model
                    elm.bind('blur', function() {   //给元素div绑定blur事件
                       scope.$apply(function() {
                          ctrl.$setViewValue(elm.html());   //当输入结束后,焦点离开div元素时,就更新model
                        });
                     });
                    // model -> view
                    ctrl.$render = function(value) {
                        elm.html(value);            //更新视图view
                    };
                    // load init value from DOM
                    ctrl.$setViewValue(elm.html());
                }
            };
        });
        </script>
      </head>
      <body>
        <div contentEditable="true" ng-model="content" title="Click to edit">Some</div>
        <pre>model = {{content}}</pre>
        <style type="text/css">
          div[contentEditable] {
            cursor: pointer;
            background-color: #D0D0D0;
          }
        </style>
      </body>
    </html>

    加油!

  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4242465.html
Copyright © 2011-2022 走看看