一般来讲表单可能遇到的问题:
1.如何数据绑定。
2.验证表单。
3.显示出错信息。
4.整个form的验证。
5.避免提交没有验证通过的表单。
6.防止多系提交。
input属性:
name
ng-model
ng-required
ng-minlength
ng-maxlength
ng-pattern
ng-change值变化时的回调
{{myForm.username.$error}}
Form控制变量
字段是否未更改
formName.inputFieldName.$pristine
字段是否更改
formName.inputFieldName.$dirty
字段有效
formName.inputFieldName.$valid
字段无效
formName.inputFieldName.$invalid
字段错误信息
formName.inputfieldName.$error
一个简单的表格的输入框的判断
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="../../vendor/bootstrap3/css/bootstrap.min.css"/> </head> <body> <div ng-app="myApp" style="margin-top: 100px;"> <form name="myForm" action="kittencup.php" ng-controller="firstController" class="container form-horizontal"> <div class="form-group" ng-class="{'has-error':myForm.username.$dirty && myForm.username.$invalid}"> <label class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> <input type="text" autocomplete="off" name="username" ng-pattern="/^[a-zA-Z]{1}/" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-model="data.username" class="form-control" placeholder="用户名"> <div ng-show="myForm.username.$dirty && myForm.username.$error.maxlength" class="alert alert-danger help-block"> 用户名长度不能超过10位 </div> <div ng-show="myForm.username.$dirty && myForm.username.$error.minlength" class="alert alert-danger help-block"> 用户名长度不能小于5位 </div> <div ng-show="myForm.username.$dirty && myForm.username.$error.pattern" class="alert alert-danger help-block"> 用户名必须已英文字母开始 </div> </div> </div> <div class="form-group" ng-class="{'has-error':myForm.password.$dirty && myForm.password.$invalid}"> <label class="col-sm-2 control-label">密 码</label> <div class="col-sm-10"> <input type="password" autocomplete="off" name="password" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-model="data.password" class="form-control" placeholder="密码"> <div ng-show="myForm.password.$dirty && myForm.password.$error.maxlength" class="alert alert-danger help-block"> 密码长度不能超过10位 </div> <div ng-show="myForm.password.$dirty && myForm.password.$error.minlength" class="alert alert-danger help-block"> 密码长度不能小于5位 </div> </div> </div> <div class="form-group" ng-class="{'has-error':myForm.passwordConfirm.$dirty && myForm.passwordConfirm.$invalid}"> <label class="col-sm-2 control-label">确认密码</label> <div class="col-sm-10"> <input type="password" autocomplete="off" name="passwordConfirm" ng-required="true" ng-model="data.passwordConfirm" class="form-control" placeholder="确认密码"> <div ng-show="myForm.password.$dirty && myForm.passwordConfirm.$dirty && data.password !== data.passwordConfirm" class="alert alert-danger help-block"> 密码和确认密码不一致 </div> </div> </div> <div class="form-group" ng-class="{'has-error':myForm.email.$dirty && myForm.email.$invalid}"> <label class="col-sm-2 control-label">邮箱</label> <div class="col-sm-10"> <input type="email" autocomplete="off" name="email" ng-required="true" ng-minlength="5" ng-maxlength="30" ng-model="data.email" class="form-control" placeholder="邮箱"> <div ng-show="myForm.email.$dirty && myForm.email.$error.maxlength" class="alert alert-danger help-block"> 邮箱长度不能超过30位 </div> <div ng-show="myForm.email.$dirty && myForm.email.$error.minlength" class="alert alert-danger help-block"> 邮箱长度不能小于5位 </div> <div ng-show="myForm.email.$dirty && myForm.email.$error.email" class="alert alert-danger help-block"> 邮箱格式不正确 </div> </div> </div> <div class="form-group" ng-class="{'has-error':myForm.blog.$dirty && myForm.blog.$invalid}"> <label class="col-sm-2 control-label">博客网址</label> <div class="col-sm-10"> <input type="url" autocomplete="off" name="blog" ng-required="true" ng-minlength="5" ng-maxlength="30" ng-model="data.blog" class="form-control" placeholder="博客网址"> <div ng-show="myForm.blog.$dirty && myForm.blog.$error.maxlength" class="alert alert-danger help-block"> 网址长度不能超过30位 </div> <div ng-show="myForm.blog.$dirty && myForm.blog.$error.minlength" class="alert alert-danger help-block"> 网址长度不能小于5位 </div> <div ng-show="myForm.blog.$dirty && myForm.blog.$error.url" class="alert alert-danger help-block"> 网址格式不正确 </div> </div> </div> <div class="form-group" ng-class="{'has-error':myForm.age.$dirty && myForm.age.$invalid}"> <label class="col-sm-2 control-label">年龄</label> <div class="col-sm-10"> <input type="number" autocomplete="off" name="age" min="10" max="99" ng-required="true" ng-model="data.age" class="form-control" placeholder="年龄"> <div ng-show="myForm.age.$dirty && myForm.age.$error.max" class="alert alert-danger help-block"> 年龄不能超过99岁 </div> <div ng-show="myForm.age.$dirty && myForm.age.$error.min" class="alert alert-danger help-block"> 年龄不能小于10岁 </div> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">性别</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" ng-required="true" name="sex" ng-model="data.sex" value="1" /> 男 </label> <label class="radio-inline"> <input type="radio" ng-required="true" name="sex" ng-model="data.sex" value="0" /> 女 </label> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">爱好</label> <div class="col-sm-10"> <label class="checkbox-inline" ng-repeat="hobby in hobbies"> <input type="checkbox" ng-model="hobby.checked" name="hobby[]" ng-checked="data.hobbies === undefined ? false : data.hobbies.indexOf(hobby.id) !== -1" ng-click="toggleHobbySelection(hobby.id)"/> {{hobby.name}} </label> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">出生地</label> <div class="col-sm-3"> <select class="form-control" ng-change="data.area = false" ng-model="data.province" ng-options="x.id as x.name for x in cities | cityFilter:0"></select> </div> <div class="col-sm-3"> <select class="form-control" ng-show="data.province" ng-model="data.area" ng-options="x.id as x.name for x in cities | cityFilter:data.province"></select> </div> <div class="col-sm-3"> <select class="form-control" ng-required="true" ng-show="data.province && data.area" ng-model="data.city" ng-options="x.id as x.name for x in cities | cityFilter:data.area"></select> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">只能输入偶数</label> <div class="col-sm-10"> <input type="text" name="even" class="form-group" placeholder="偶数" ng-model="data.even" even> <div ng-show="myForm.even.$error.even" class="alert alert-danger help-block"> 数字必须是偶数 </div> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">个人介绍</label> <div class="col-sm-10"> <custom-text-area ng-model="data.introduct">aaa</custom-text-area> <custom-text-area ng-model="data.introduct"></custom-text-area> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default" ng-disabled="myForm.$invalid || data.hobbies === undefined || data.hobbies.length === 0">注册</button> <button type="reset" class="btn btn-default" ng-click="reset()">重置</button> </div> </div> </form> </div> <script type="text/javascript" src="../../vendor/angular/angularjs.js"></script> <script type="text/javascript" src="app/index.js"></script> </body> </html>
angular.module('myApp', []) .filter('cityFilter', function () { return function (data, parent) { var filterData = []; angular.forEach(data, function (obj) { if (obj.parent === parent) { filterData.push(obj); } }) return filterData; } }) .directive('even',function(){ return { require : 'ngModel', link:function(scope,elm,attrs,ngModelController){ ngModelController.$parsers.push(function(viewValue){ if(viewValue % 2 === 0){ ngModelController.$setValidity('even',true); }else{ ngModelController.$setValidity('even',false); } return viewValue; }); // ngModelController.$formatters.push(function(modelValue){ // return modelValue + 'kittencup'; // }) } }; }) .directive('customTextArea',function(){ return { restrict:'E', template:'<div contenteditable="true"></div>', replace:true, require : 'ngModel', link:function(scope,elm,attrs,ngModelController){ // view->model elm.on('keyup',function(){ scope.$apply(function(){ ngModelController.$setViewValue(elm.html()); }); }) ngModelController.$render = function(){ elm.html(ngModelController.$viewValue); } } }; }) .controller('firstController', ['$scope', function ($scope) { var that = this; $scope.hobbies = [ { id: 1, name: '玩游戏' }, { id: 2, name: '写代码' }, { id: 3, name: '睡觉' }, ]; $scope.cities = [ { name: '上海', parent: 0, id: 1 }, { name: '上海市', parent: 1, id: 2 }, { name: '徐汇区', parent: 2, id: 8 }, { name: '长宁区', parent: 2, id: 3 }, { name: '北京', parent: 0, id: 4 }, { name: '北京市', parent: 4, id: 5 }, { name: '东城区', parent: 5, id: 6 }, { name: '丰台区', parent: 5, id: 7 }, { name: '浙江', parent: 0, id: 9 }, { name: '杭州', parent: 9, id: 100 }, { name: '宁波', parent: 9, id: 11 }, { name: '西湖区', parent: 100, id: 12 }, { name: '北仑区', parent: 11, id: 13 } ]; $scope.data = { hobbies: [1, 2], city: 3 }; // 先保留一份默认值 $scope.origData = angular.copy($scope.data); $scope.reset = function(){ $scope.data = angular.copy($scope.origData); that.initCity(); $scope.myForm.$setPristine(); } // 让城市关联使用 this.findCityId = function (parent) { var parentId; angular.forEach($scope.cities, function (city) { if (city.id === parent) { parentId = city.parent; return; } }) return parentId; } this.initCity = function(){ if ($scope.data.city !== undefined) { $scope.data.area = this.findCityId($scope.data.city); $scope.data.province = this.findCityId($scope.data.area); } } // 第一次打开页面 需要初始化一下 this.initCity.call(this); $scope.toggleHobbySelection = function (id) { var index = -1; if ($scope.data.hobbies === undefined) { $scope.data.hobbies = []; } else { index = $scope.data.hobbies.indexOf(id); } if (index === -1) { $scope.data.hobbies.push(id); } else { $scope.data.hobbies.splice(index, 1); } } }]);
===========================================
myForm.username.$dirty 如果表单有更改则为true,如果没有更改则为false。
myForm.username.$error.maxlength 如果超出则为true,如果没有超出则为false。
ng-class="{'has-error':myForm.password.$dirty && myForm.password.$invalid}" 这句的意思是为了可以让写错后,边框变红。
autocomplete="off" 关闭自动提示的功能
ng-options="x.id as x.name for x in cities | cityFilter:0" 看链接:http://each.sinaapp.com/angular/tutorial/ng-options.html
ng-model 是angular原生的directive
可以通过require ngModel可以更深入的去处理数据的双向绑定。
ngModel里的属性
$parsers属性,保存了从viewValue向modelValue绑定过程中的处理函数,它们将来会依次执行。
$formatters它保存的是从modelValue向viewValue绑定过程中的处理函数
$setViewValue 当view发生了某件事情时,从view向model绑定调用
$setViewValue
$render
$setValidity
$viewValue
$modelValue
当reset的按钮同时又click事件时,先执行本身的reset然后执行click事件。
注意表单中这几个位置的写法,ng-model必须是$scope中给出的,不能写user.