Resumen personal
one: 一般来讲表单可能遇到的问题
1.如何数据绑定
2.验证表单
3.显示出错信息
4.整个form的验证
5.避免提交没有验证通过的表单
6.防止多次提交
two: input表单验证需要的属性
* name 名字(这里需要注意:不光是input元素需要,最外层的form标签也需要一个name属性)
* ng-model 绑定的数据
* ng-required 是否必填 (true/false)
* ng-minlength 最小长度
* ng-maxlength 最大长度
* ng-pattrn 匹配模式(正则匹配)
* ng-change 值变化时的回调
three: 表单验证css样式
* ng-valid 当表单验证通过时的设置
* ng-invalid 当表单验证失败时的设置
* ng-pristine 表单的未被动之前拥有
* ng-dirty 表单被动过之后拥有
four: formName控制变量(返回的错误信息true/false);
* formName.inputName.$pristine 字段是否未更改
* formName.inputName.$dirty 字段是否更改
* formName.inputName.$valid 字段有效
* formName.inputName.$invalid 字段无效
* formName.inputName.$error 字段错误信息(是一个对象,里面是每一个判断属性的bol值)
这里的formName就是form标签上的name属性,inputName就是input标签上name属性,最后的$xxx则是angularjs内置的变量
five: Form的方法;
* $setPristine 重置表单时可以用 将表单复位原始状态,包括class,$dirty,$pristine这三个方法
$scope.myForm.$setPristine(); $scope.myForm就是表单form标签的name,$setPristine()是它下面的一个重置方法
suplemento
1. 省市三级联动select标签,可以写成
<select class="form-control" ng-change="data.area = false" ng-model="data.province" ng-options="x.id as x.name for x in citys | cityFilter:0"></select>
ng-options就是代替了<option value='x.id'></option>标签
ng-options里的x.id as x.name for x in citys就是循环的city城市数组,x.id就是option的vaue值,x.name就是option显示的值
2. 自定义过滤器的一种用法(只是在本篇文章中的案例中涉及到了,在此粗略的总结一下,后面写到过滤器总结的时候会详细总结)
var app=angular.module('app',[]);
app.fliter('cityFilter',function(){
//参数一,在循环后用的话就是默认当条数据,参数二,就是用过滤器时冒号后跟的参数
// 例: ng-options="x.id as x.name for x in citys | cityFilter:0"; 0就是第二个参数,第一个参数默认就是循环的当前数据
return function(data,id){
var formData=[];
// 在这里假设我们要过留下数据的id为0的;
angular.forEach(data,function(v){
if(v.id===id){
formData.push(v);
}
})
}
return formData;
})
3. 如果工作中用到的是这样的表单验证,submit提交时,可以用来控制提交按钮是否禁止
例: <button type="submit" class="btn btn-default" ng-disabled="myForm.$invalid || data.hobbies === undefined || data.hobbies.length === 0">注册</button>
前提是表单元素必须要加上ng-required='tru/e',checkbox除外,checkbox可以用逻辑来控制
4. ng-model; //后面详细总结指令各个属性时在做详细总结,在此涉及一些
* ng-model是angular原生的directive
* 可以通过require ngModel可以更深的去处理数据的双向绑定
* 使用方法:在directive指令中的require定义require:'ngModel'
例:app.directive("directive", [ "$rootScope", function ($rootScope) {
return {
restrict: "E",
scope: {
changeCbk: "&",
},
require: "ngModel", // 这个就是外面的ng-model绑定的数据
link: function (scope, element, attr, ngModelCtrl){
ngModelCtrl就是ngModel
}
}
]});
* ngModel里的属性
& $parsers属性,保存了从viewValue向modelValue绑定过程中的处理函数,他们将来会依次执行
& $formatters,他保存的是从modelValue向viewValue绑定过程中的处理函数
& $setViewValue,当view发生了某件事情时,从view向model绑定调用
$setViewValue把viewValue保存下来
& $render 当模型发生变化时,应该怎么去更新视图,从model向view绑定
调用ctrl.$render方法,将viewValue渲染到页面上
& $setValidity 设置验证结果
& $viewValue 视图的值
& $modelValue 模型里的值
Caso 1: combinado con el estilo bootstrap, use la función de verificación incorporada de angularjs para lograr la verificación del formulario.
<!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>
Caso 1: index.js
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();
console.log('aaaaaaaaaaaaaa-----',$scope.myForm);
$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);
}
}
}]);
Caso 2: Igual que el Caso 1, pero el efecto es diferente
<!DOCTYPE html>
<html lang="en" ng-app='App'>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>表单提示</title>
<link rel="stylesheet" href="../../angularjs/bootstrap-3.3.7-dist/css/bootstrap.min.css">
<style>
body{
padding-top: 50px;
}
</style>
</head>
<body>
<div ng-controller="firstController" class="container">
<div class="col-md-6">
<form role="form" name="myForm" ng-submit="submitForm(myForm.$valid)" class="form-horizontal" novalidate>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="name">1.必填项</label>
</div>
<div class="col-md-8">
<input class="form-control" id="name" name="name" type="text" required ng-model='user.name' />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.name.$dirty && myForm.name.$valid"></span>
</div>
</div>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="minlength">2.最小长度=5</label>
</div>
<div class="col-md-8">
<input type="text" id="minlength" name="minlength" ng-minlength="5" ng-model="user.minlength"
class="form-control" />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.minlength.$dirty && myForm.minlength.$valid"></span>
</div>
</div>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="maxlength">3.最大长度=20</label>
</div>
<div class="col-md-8">
<input type="text" id="maxlength" name="maxlength" ng-model="user.maxlength" ng-maxlength="20"
class="form-control" />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.maxlength.$dirty && myForm.maxlength.$valid"></span>
</div>
</div>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="pattern">4. 模式匹配</label>
</div>
<div class="col-md-8">
<input type="text" id="pattern" name="pattern" ng-model="user.pattern"
ng-pattern="/^[a-zA-Z]*\d$/" class="form-control" />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.pattern.$dirty && myForm.pattern.$valid"></span>
</div>
</div>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="email">5. 电子邮件</label>
</div>
<div class="col-md-8">
<input type="email" id="email" name="email" ng-model="user.email" class="form-control" />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.email.$dirty && myForm.email.$valid"></span>
</div>
</div>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="age">6. 数字</label>
</div>
<div class="col-md-8">
<input type="number" id="age" name="age" ng-model="user.age" class="form-control" />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.age.$dirty && myForm.age.$valid"></span>
</div>
</div>
<div class="form-group has-feedback">
<div class="col-md-4">
<label for="url"> 7. URL</label>
</div>
<div class="col-md-8">
<input type="url" id="url" name="url" ng-model="user.url" class="form-control" />
<span class="glyphicon glyphicon-ok form-control-feedback"
ng-show="myForm.url.$dirty && myForm.url.$valid"></span>
</div>
</div>
<div class="form-group text-center">
<input class="btn btn-primary btn-lg" ng-disabled="myForm.$invalid" type="submit" value="提交" />
</div>
</form>
</div>
<div class="col-md-12">
1.必填项:{
{user.name}}
$pristine 【没修改】:{
{myForm.name.$pristine }}
$dirty【修改过】:{
{myForm.name.$dirty}}
$invalid【验证失败】:{
{myForm.name.$invalid}}
$invalid【验证成功】:{
{myForm.name.$valid}}
required:{
{myForm.name.$error.required}}
<br>
2.最小长度=5:{
{user.minlength}}
$pristine 【没修改】:{
{myForm.minlength.$pristine }}
$dirty【修改过】:{
{myForm.minlength.$dirty}}
$invalid【验证失败】:{
{myForm.minlength.$invalid}}
$invalid【验证成功】:{
{myForm.minlength.$valid}}
$error【错误详情】:{
{myForm.minlength.$error}} <br>
3.最大长度=20:{
{user.maxlength}}
$pristine 【没修改】:{
{myForm.maxlength.$pristine }}
$dirty【修改过】:{
{myForm.maxlength.$dirty}}
$invalid【验证失败】:{
{myForm.maxlength.$invalid}}
$invalid【验证成功】:{
{myForm.maxlength.$valid}}
$error【错误详情】:{
{myForm.maxlength.$error}} <br>
4.模式匹配:{
{user.pattern}}
$pristine 【没修改】:{
{myForm.pattern.$pristine }}
$dirty【修改过】:{
{myForm.pattern.$dirty}}
$invalid【验证失败】:{
{myForm.pattern.$invalid}}
$invalid【验证成功】:{
{myForm.pattern.$valid}}
$error【错误详情】:{
{myForm.pattern.$error}} <br>
5.电子邮件:{
{user.email}}
$pristine 【没修改】:{
{myForm.email.$pristine }}
$dirty【修改过】:{
{myForm.email.$dirty}}
$invalid【验证失败】:{
{myForm.email.$invalid}}
$invalid【验证成功】:{
{myForm.email.$valid}}
$error【错误详情】:{
{myForm.email.$error}} <br>
6.数字:{
{user.age}}
$pristine 【没修改】:{
{myForm.age.$pristine }}
$dirty【修改过】:{
{myForm.age.$dirty}}
$invalid【验证失败】:{
{myForm.age.$invalid}}
$invalid【验证成功】:{
{myForm.age.$valid}}
$error【错误详情】:{
{myForm.age.$error}} <br>
7.URL:{
{user.url}}
$pristine 【没修改】:{
{myForm.url.$pristine }}
$dirty【修改过】:{
{myForm.url.$dirty}}
$invalid【验证失败】:{
{myForm.url.$invalid}}
$invalid【验证成功】:{
{myForm.url.$valid}}
$error【错误详情】:{
{myForm.url.$error}} <br>
</div>
</div>
<script src="../../angularjs/jquery-1.12.4.js"></script>
<script src="../../angularjs/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
<script src="../../angularjs/angular-1.5.8/angular.js"></script>
<script>
var app=angular.module('App',[]);
app.controller('firstController',['$scope',function($scope){
}])
</script>
</body>
</html>