点击查看AngularJS系列目录
转载请注明出处:http://www.cnblogs.com/leosx/



Angular表单

input, select, textarea控件都是给用户输入数据用的。窗体和控件提都提供了验证服务,使得在用户输入了无效数据的情况下,提交表单之前就可以得到知道。这样的验证远远比只在服务端进行验证好得多,因为在前端验证,用户可以得到很好的用户输入错误的反馈!提高用户体验。请记住,在客户端进行验证是用户体验的非常重要的组成部分。但是它很容易就可以被篡改,所以我们是不能信赖前端验证的,后端依旧得进行验证。

 

一个简单的表单

文件一:index.html

  1. <div ng-controller="ExampleController">
  2. <form novalidate class="simple-form">
  3. Name: <input type="text" ng-model="user.name" /><br />
  4. E-mail: <input type="email" ng-model="user.email" /><br />
  5. Gender: <input type="radio" ng-model="user.gender" value="male" />male
  6. <input type="radio" ng-model="user.gender" value="female" />female<br />
  7. <input type="button" ng-click="reset()" value="Reset" />
  8. <input type="submit" ng-click="update(user)" value="Save" />
  9. </form>
  10. <pre>user = {{user | json}}</pre>
  11. <pre>master = {{master | json}}</pre>
  12. </div>
  13.  
  14. <script>
  15. angular.module('formExample', [])
  16. .controller('ExampleController', ['$scope', function($scope) {
  17. $scope.master = {};
  18.  
  19. $scope.update = function(user) {
  20. $scope.master = angular.copy(user);
  21. };
  22.  
  23. $scope.reset = function() {
  24. $scope.user = angular.copy($scope.master);
  25. };
  26.  
  27. $scope.reset();
  28. }]);
  29. </script>

 

效果图:

当点击Reset按钮的时候,就会把user对象给重置为原来保存的对象。

请注意:novalidate 用来禁用掉原生的浏览器表单验证。如果验证不通过,那么ngModel 所绑定的model的对应值是不会改变的。

 

样式的使用

使用样式,我们可以更好的控制表单控件,例如:ngModel 指令就为对应的元素增加了如下样式:

1、ng-valid: 模型(model)验证通过

2、ng-invalid: 模型(model)验证失败

3、ng-valid-[key]: 通过$setValidity增加的验证通过的密匙()

4、ng-invalid-[key]: 通过$setValidity增加的验证失败的密匙

5、ng-pristine: 还没有与controller进行互动。

6、ng-dirty: 控制器与之有互动

7、ng-touched: 已经失去控制

8、ng-untouched: 还未失去控制

9、ng-pending: 异步验证($asyncValidators )还未结束

下面的示例使用CSS来显示每个表单控件的有效性。例子中,user.nameuser.email 是必须的,当失去焦点时,会进行验证,如果验证不通过,那么背景色会变成红色的。这确保了用户不会忽略掉错误,知道验证通过了,才会同步到controller的model中去。

文件一:index.html

  1. <div ng-controller="ExampleController">
  2. <form novalidate class="css-form">
  3. Name: <input type="text" ng-model="user.name" required /><br />
  4. E-mail: <input type="email" ng-model="user.email" required /><br />
  5. Gender: <input type="radio" ng-model="user.gender" value="male" />male
  6. <input type="radio" ng-model="user.gender" value="female" />female<br />
  7. <input type="button" ng-click="reset()" value="Reset" />
  8. <input type="submit" ng-click="update(user)" value="Save" />
  9. </form>
  10. <pre>user = {{user | json}}</pre>
  11. <pre>master = {{master | json}}</pre>
  12. </div>
  13.  
  14. <style type="text/css">
  15. .css-form input.ng-invalid.ng-touched {
  16. background-color: #FA787E;
  17. }
  18.  
  19. .css-form input.ng-valid.ng-touched {
  20. background-color: #78FA89;
  21. }
  22. </style>
  23.  
  24. <script>
  25. angular.module('formExample', [])
  26. .controller('ExampleController', ['$scope', function($scope) {
  27. $scope.master = {};
  28.  
  29. $scope.update = function(user) {
  30. $scope.master = angular.copy(user);
  31. };
  32.  
  33. $scope.reset = function() {
  34. $scope.user = angular.copy($scope.master);
  35. };
  36.  
  37. $scope.reset();
  38. }]);
  39. </script>
效果图:
可以看到,用户名name验证通过了,但是邮件验证失败,未通过。

 

绑定表单状态和控件状态

Angular的一个表单就是一个FormController的实例对象。表单的实例对象可以使用name属性有选择的发布到scope上去。

同样的,input控件都会具有一个NgModelController的实例ngModel 指令。这种input控件(表单实例)的实例可以通过name 属性所对应的控件上,再发布一个属性。

这使我们能够扩展上面的例子有以下功能:

1、如果有自定义错误,那么用户和控件交互后,会被触发判断,如果有错,将会立即显示提示消息(如果设置了$touched,那么手机上触摸也会执行)。

2、当用户点击submit按钮($submitted)的时候,即使之前没有执行交互,那么一样会触发自定义验证,并显示错误消息。

文件一:index.html

  1. <div ng-controller="ExampleController">
  2. <form name="form" class="css-form" novalidate>
  3. Name:
  4. <input type="text" ng-model="user.name" name="uName" required="" />
  5. <br />
  6. <div ng-show="form.$submitted || form.uName.$touched">
  7. <div ng-show="form.uName.$error.required">Tell us your name.</div>
  8. </div>
  9.  
  10. E-mail:
  11. <input type="email" ng-model="user.email" name="uEmail" required="" />
  12. <br />
  13. <div ng-show="form.$submitted || form.uEmail.$touched">
  14. <span ng-show="form.uEmail.$error.required">Tell us your email.</span>
  15. <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
  16. </div>
  17.  
  18. Gender:
  19. <input type="radio" ng-model="user.gender" value="male" />male
  20. <input type="radio" ng-model="user.gender" value="female" />female
  21. <br />
  22. <input type="checkbox" ng-model="user.agree" name="userAgree" required="" />
  23.  
  24. I agree:
  25. <input ng-show="user.agree" type="text" ng-model="user.agreeSign" required="" />
  26. <br />
  27. <div ng-show="form.$submitted || form.userAgree.$touched">
  28. <div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
  29. </div>
  30.  
  31. <input type="button" ng-click="reset(form)" value="Reset" />
  32. <input type="submit" ng-click="update(user)" value="Save" />
  33. </form>
  34. <pre>user = {{user | json}}</pre>
  35. <pre>master = {{master | json}}</pre>
  36. </div>

 

文件二:script.js

  1. angular.module('formExample', [])
  2. .controller('ExampleController', ['$scope', function($scope) {
  3. $scope.master = {};
  4.  
  5. $scope.update = function(user) {
  6. $scope.master = angular.copy(user);
  7. };
  8.  
  9. $scope.reset = function(form) {
  10. if (form) {
  11. form.$setPristine();
  12. form.$setUntouched();
  13. }
  14. $scope.user = angular.copy($scope.master);
  15. };
  16.  
  17. $scope.reset();
  18. }]);

效果图:

 

自定义模型的更新触发时机(WPF中的更新时间)

默认情况下,任何内容的改变将触发表单验证和model的更新。你可以通过ngModelOptions指令绑定到一个事件集合中来重写触发的时间,例如:ng-model-options="{ updateOn: 'blur' }" 将会在控件失去焦点后执行表单验证和更新Model。你可以使用空格来分割多个事件的触发验证和更新的时间。例如:ng-model-options="{ updateOn: 'mousedown blur' }"

 

如果你想更改默认的触发时机,你可以使用"default" 来指定:

例如:ng-model-options="{ updateOn: 'default blur' }"

 

下面的例子展示了如何重写更新时机。修改触发时机为失去焦点时执行触发验证和更新。

文件一:index.html

  1. <div ng-controller="ExampleController">
  2. <form>
  3. Name:
  4. <input type="text" ng-model="user.name" ng-model-options="{ updateOn: 'blur' }" /><br />
  5. Other data:
  6. <input type="text" ng-model="user.data" /><br />
  7. </form>
  8. <pre>username = "{{user.name}}"</pre>
  9. <pre>userdata = "{{user.data}}"</pre>
  10. </div>

 

文件二:script.js

  1. angular.module('customTriggerExample', [])
  2. .controller('ExampleController', ['$scope', function($scope) {
  3. $scope.user = {};
  4. }]);

效果演示:

 

延迟更新和验证时间

你可以使用ngModelOptions 指令来延迟Model的验证和更新时间。这种延迟同样适用于parsers(解析器)、validators(验证器)、model标签(eg:$dirty 或者 $pristine)

例如:ng-model-options="{ debounce: 500 }" 会在出发之后延迟500毫秒再执行验证和更新model。

如果自定义的触发器被使用,那么我们可以使用debounce来为每个自定义的触发器指定延迟时间。

例如:ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"

如果这些属性被加到一个元素上去,那么这种机制会应用到这个元素下的所有子元素下,也就是会继承这种机制,除非子元素重写了这种机制。

我们来看下面的例子,验证动作和model的更新将会在最后一次更改input内容250毫秒后执行。

文件一:index.html

  1. <div ng-controller="ExampleController">
  2. <form>
  3. Name:
  4. <input type="text" ng-model="user.name" ng-model-options="{ debounce: 250 }" /><br />
  5. </form>
  6. <pre>username = "{{user.name}}"</pre>
  7. </div>

 

文件二:script.js

  1. angular.module('debounceExample', [])
  2. .controller('ExampleController', ['$scope', function($scope) {
  3. $scope.user = {};
  4. }]);

效果图:

 

自定义验证

Angular提供了对HTML5最常用的表单控件的实现(text, number, url, email, date, radio, checkbox),同样的,相同的验证也有被重写:(required, pattern, minlength, maxlength, min, max).

通过自定义指令,你可以通过对ngModelController对象的$validators 实例(也就是ng-model指令)添加自己的验证功能,在下面的示例中,我们会用到。

$validators 对象上的每一个验证函数都将modelValueviewValue 做为参数。接着Angular会调用$setValidity方法,它会返回(true: valid【验证通过】, false: invalid【验证失败】)。验证函数会在每次输入改变的时候执行($setViewValue 被调用),或者触发时机被修改了,一样会触发验证。当分别成功执行了$parsers$formatters方法后,会执行验证(Validation),如果验证错误,那么会把错误信息保存到ngModelController.$error对象中去。

此外,$asyncValidators 对象可以进行异步验证,它就相当于使用$http 去调用后台执行验证。这个验证方法必须承诺当验证通过时,返回resolved;当验证失败时,返回rejected ;执行异步验证的结果将会保存到ngModelController.$pending中去。

 

下面的例子中,我们创建了两个指令:

1、integer 指令用于验证输入的值是否是数字(int类型),例如:1.23 将会验证失败,因为它有小数部分。注意,我们这里验证的是view(视图)中的控件的输入值,并不是控件对应的model的值。因为只有成功的执行了$parsers方法后,才会将数据更新到model的对应属性中去。

2、username 指令用于异步验证用户名。如果该用户已经存在,那么会给出提示!这里,我们使用$q来模拟从服务器验证。

文件一:index.html

  1. <form name="form" class="css-form" novalidate>
  2. <div>
  3. Size (integer 0 - 10):
  4. <input type="number" ng-model="size" name="size"
  5. min="0" max="10" integer />{{size}}<br />
  6. <span ng-show="form.size.$error.integer">The value is not a valid integer!</span>
  7. <span ng-show="form.size.$error.min || form.size.$error.max">
  8. The value must be in range 0 to 10!</span>
  9. </div>
  10.  
  11. <div>
  12. Username:
  13. <input type="text" ng-model="name" name="name" username />{{name}}<br />
  14. <span ng-show="form.name.$pending.username">Checking if this name is available...</span>
  15. <span ng-show="form.name.$error.username">This username is already taken!</span>
  16. </div>
  17.  
  18. </form>

 

文件二:script.js

  1. var app = angular.module('form-example1', []);
  2.  
  3. var INTEGER_REGEXP = /^\-?\d+$/;
  4. app.directive('integer', function() {
  5. return {
  6. require: 'ngModel',
  7. link: function(scope, elm, attrs, ctrl) {
  8. ctrl.$validators.integer = function(modelValue, viewValue) {
  9. if (ctrl.$isEmpty(modelValue)) {
  10. // consider empty models to be valid
  11. return true;
  12. }
  13.  
  14. if (INTEGER_REGEXP.test(viewValue)) {
  15. // it is valid
  16. return true;
  17. }
  18.  
  19. // it is invalid
  20. return false;
  21. };
  22. }
  23. };
  24. });
  25.  
  26. app.directive('username', function($q, $timeout) {
  27. return {
  28. require: 'ngModel',
  29. link: function(scope, elm, attrs, ctrl) {
  30. var usernames = ['Jim', 'John', 'Jill', 'Jackie'];
  31.  
  32. ctrl.$asyncValidators.username = function(modelValue, viewValue) {
  33.  
  34. if (ctrl.$isEmpty(modelValue)) {
  35. // consider empty model valid
  36. return $q.when();
  37. }
  38.  
  39. var def = $q.defer();
  40.  
  41. $timeout(function() {
  42. // Mock a delayed response
  43. if (usernames.indexOf(modelValue) === -1) {
  44. // The username is available
  45. def.resolve();
  46. } else {
  47. def.reject();
  48. }
  49.  
  50. }, 2000);
  51.  
  52. return def.promise;
  53. };
  54. }
  55. };
  56. });

 

效果图:

 

修改内置的验证机制

自从Angular使用了$validators来进行校验数据,你就可以很轻松的替换掉默认的数据验证方式。下面的例子中,我们使用自定义的指令重写了表单中邮件input[email] 的验证方式。注意,你也可以使用ng-pattern 指令来进一步限制验证。

文件一:index.html

  1. <form name="form" class="css-form" novalidate>
  2. <div>
  3. Overwritten Email:
  4. <input type="email" ng-model="myEmail" overwrite-email name="overwrittenEmail" />
  5. <span ng-show="form.overwrittenEmail.$error.email">This email format is invalid!</span><br>
  6. Model: {{myEmail}}
  7. </div>
  8. </form>

文件二:script.js

  1. var app = angular.module('form-example-modify-validators', []);
  2.  
  3. app.directive('overwriteEmail', function() {
  4. var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;
  5.  
  6. return {
  7. require: 'ngModel',
  8. restrict: '',
  9. link: function(scope, elm, attrs, ctrl) {
  10. // only apply the validator if ngModel is present and Angular has added the email validator
  11. if (ctrl && ctrl.$validators.email) {
  12.  
  13. // this will overwrite the default Angular email validator
  14. ctrl.$validators.email = function(modelValue) {
  15. return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
  16. };
  17. }
  18. }
  19. };
  20. });

 

效果图:

 

实现自定义表单控件(使用 ngModel)

Angular实现了基本的HTML表单控件(input, select, textarea),他们可以满足大部分需求了。为了更好的灵活性,你也可以通过指令来自定义属于自己的表单控件。

为了使得自定义控件可以很好的和ngModel 指令进行数据的双向通信,你需要:

1、实现$render 方法,它负责在NgModelController.$formatters后,呈现数据。

2、调用$setViewValue 方法,当用户与控件进行交互,需要进行model的更新时。这个动作通常在一个DOM事件监听器里完成的。

点击这里,查看关于$compileProvider.directive 的更多信息。

下面的例子展示了如何为contentEditable元素增加的数据的双向绑定。

文件一:index.html

  1. <div contentEditable="true" ng-model="content" title="Click to edit">Some</div>
  2. <pre>model = {{content}}</pre>
  3.  
  4. <style type="text/css">
  5. div[contentEditable] {
  6. cursor: pointer;
  7. background-color: #D0D0D0;
  8. }
  9. </style>

 

文件二:script.js

  1. angular.module('form-example2', []).directive('contenteditable', function() {
  2. return {
  3. require: 'ngModel',
  4. link: function(scope, elm, attrs, ctrl) {
  5. // view -> model
  6. elm.on('blur', function() {
  7. ctrl.$setViewValue(elm.html());
  8. });
  9.  
  10. // model -> view
  11. ctrl.$render = function() {
  12. elm.html(ctrl.$viewValue);
  13. };
  14.  
  15. // load init value from DOM
  16. ctrl.$setViewValue(elm.html());
  17. }
  18. };
  19. });

 

效果图:

Angularjs-Forms(表单)的更多相关文章

  1. 【AngularJs】---表单验证

    1. 必填项 验证某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: <input type="text" required /> 2 ...

  2. angularJS 过滤器 表单验证

    过滤器1.filter的作用就是接收一个输入,通过某个规则进行处理,然后返回处理后的结果,主要用于数据的格式化.2.内置过滤器(1)Currency(货币)将一个数值格式化为货币格式,默认为$(2)D ...

  3. AngularJS实现表单手动验证和表单自动验证

    AngularJS的表单验证大致有两种,一种是手动验证,一种是自动验证.一.手动验证 所谓手动验证是通过AngularJS表单的属性来验证.而成为AngularJS表单必须满足两个条件: 1.给for ...

  4. 页面注册系统--使用forms表单结合ajax

    页面注册系统--使用forms表单结合ajax 在Django中通过forms构建一个表单 1.urls.py 配置路由 from django.conf.urls import url from d ...

  5. Python的Django框架中forms表单类的使用方法详解

    用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础form对象,本文就Python的Django框架中forms表单类的使用方法详解. Form表单的功能 自动生成HTML ...

  6. 基于angularJS的表单验证练习

    今天看了一下angularJS的表单验证,看的有点云里雾里(也有可能是雾霾吸多了),于是做了一个小练习来巩固一下. html: <div ng-controller="Aaa" ...

  7. django实现密码加密的注册(数据对象插入)-结合forms表单实现表单验证

    forms表单 #_*_coding:utf-8_*_ from django import forms class regis(forms.Form): username = forms.CharF ...

  8. 夺命雷公狗—angularjs—3—表单验证的高级用法

    其实我们的angularjs都是是块状代码,其实是可以在实际开发中保存下来以后就可以达到重复利用的目的了.. 废话不多说,直接上代码: <!doctype html> <html l ...

  9. AngularJS 模块& 表单

    模块定义了一个应用程序. 模块是应用程序中不同部分的容器. 模块是应用控制器的容器. 控制器通常属于一个模块. 应用("myApp") 带有控制器 ("myCtrl&qu ...

  10. angularjs的表单验证

    angularjs内置了常用的表单验证指令,比如min,require等.下面是演示: <!DOCTYPE html> <html> <head> <meta ...

随机推荐

  1. 【MD5解密】免费帮大家解MD5

    除睡觉时间外最慢2小时内回复!结合各种国内外免费收费引擎和高效彩虹表,需要解的在评论下方评论即可

  2. 【渗透课程】第四篇-Web安全之信息探测

    Web之信息探测,从这篇开始就正式进入了Web渗透实战过程了,嗯,前面都是讲基础,下面我们来讲Web中的信息探测. 信息探测,主要的目的 收集目标服务器系统信息(IP,服务器所用系统等) 收集目标网站 ...

  3. 转每天一个linux命令(5):rm 命令

    昨天学习了创建文件和目录的命令mkdir ,今天学习一下linux中删除文件和目录的命令: rm命令.rm是常用的命令,该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所 ...

  4. Django编写RESTful API(六):ViewSets和Routers

    欢迎访问我的个人网站:www.comingnext.cn 前言 在本系列的文章中,我在第一篇和第二篇文章中写的编写Django视图时,使用的都是基于函数的方法,并且每个视图函数之前都会加一个djang ...

  5. bam文件softclip , hardclip ,markduplicate的探究

      测序产生的bam文件,有一些reads在cigar值里显示存在softclip,有一些存在hardclip,究竟softclip和hardclip是怎么判断出来的,还有是怎么标记duplicate ...

  6. javaSE基础之 LinkedList的底层简单实现

    这里贴上LinkedList底层的简单实现 package com.yck.mylinkedlist; public class Node { private Node previous; //上一结 ...

  7. 记一次JavaWeb网站技术架构总结

    题记 工作也有几多年了,无论是身边遇到的还是耳间闻到的,多多少少也积攒了自己的一些经验和思考,当然,博主并没有太多接触高大上的分布式架构实践,相对比较零碎,随时补充. 俗话说的好,冰冻三尺非一日之寒, ...

  8. 原创 :nfs软件服务利用ansible实现一键化部署

    [root@m01 tools]# cat nfspeizhi.shcat >>/etc/exports<<EOF /data 172.16.1.0/24(rw,sync)EO ...

  9. jQuery的基础跟JS的正则

    大家好,我是唯芸星,这是我的一点点学过的知识,呈现给大家                   1:正则表达式 包括: 1:正则表达式包括两部分 ①:定义正则表达式的规则 ②:正则表达式的规模(i/g/ ...

  10. px,em,rem,vw单位在网页和移动端的应用

    px: 是网页设计中最常用的单位,然而1px到底是多大长,恐怕没有人能回答上来 它用来表示屏幕设备物理上能显示的最小的一个点,这个点不是固定宽度的,不同设备上点的长度.比例有可能会不同. 假设:你现在 ...