Open jiayisheji opened 7 years ago
书接上回,上面已经把angular表单验证基本东西都介绍完了。先说几个辅助指令。
表单辅助指令
- ngDisabled:接受一个表达式,如果表达式为真, 指定的属性“disabled”会被设到元素上。一般用在按钮上面。
<button type="submit" ng-disabled="login.$invalid">提交</button>
这个就是如果未通过验证就不能提交
- ngChecked:接受一个表达式,如果表达式为真,则在元素上放置"checked"属性。一般用在checkbox,radio这2个表单元素上
- ngReadonly:接受一个表达式,如果表达式为真, 指定的属性"readonly" 会被设到元素上。一般都放在输入框,有了这个属性,就不能输入了。
- ngTrim :默认会把首尾空格去掉,如果设置为false,Angular将不自动去除输入内容的空格。一般存在输入元素input[type=text],textarea上。
- min:当输入的值小于min时,设置min 验证错误。一般只存在时间类型和数字类型,例如:input[type=dateTimeLocal],input[type=date],input[type=month],input[type=number],input[type=time],input[type=week]。
- max:当输入的值大于max时,设置max验证错误。一般只存在时间类型和数字类型,例如:input[type=dateTimeLocal],input[type=date],input[type=month],input[type=number],input[type=time],input[type=week]。
- ngValue:当被选中时,value会被置为表达式的值。只存在input[type=radio],其他表单原生也可以使用,不过没有什么意义,因为有ng-model,实际生成value不会改变任何东西。
- ngTrueValue:当被选中时,value会被置为表达式的值。只存在input[type=checkbox]
- ngFalseValue:当未被选中时,value会被置为表达式的值。只存在input[type=checkbox]
- ngSelected:接受一个表达式,如果表达式为真, 指定的属性"selected" 会被设到元素上。一般存在option上。
- ngOptions: 根据参数自动生成option标签。几种常见的写法,一般只用于select标签上 数组写法:
label for value in array select as label for value in array label group by group for value in array select as label group by group for value in array track by trackexpr
哈希对象写法:
label for (key , value) in Object select as label for (key , value) in Object label group by group for (key, value) in Object select as label group by group for (key, value) in Object
解释:
array / Object:用于进行迭代的结果为一个数组或对象的表达式。 value: 局部变量,迭代期间指向array中的每个条目,或Object的每个属性值。 key: 局部变量,迭代期间指向Object的属性名称。 label: 这个表达式的结果作为<option>元素的标签。表达式通常指向value 变量(value.propertyName)。 select:这个表达式的结果会绑定到父<select>元素的模型上。如果未指定,select表达式默认为value。 group: 这个表达式的结果会被用于使用<optgroup> DOM 元素分组选项。 trackexpr: 应用于对象数组。表达式的结果被用唯一标识数组中的对象。 trackexpr通常指向value变量(如value.propertyName)。
特殊指令 ngForm
上面都是ng扩展的指令,还有一个指令angular特别提供的ngForm。 在html里面form套form这个玩意不能共存的。但是很多时候我们在写angular是数据都是动态生成的,那么表单元素也是动态生成的,就会出现一些不方便的地方,这个时候ngForm就出现了,他可以这么写
标准写法 <ng-form name="addressList" ng-repeat="item in addressList"> 收货地址:<input type="address" name="address" ng-model="item.address"> <br /> </ng-form> 兼容老旧ie <div ng-form="addressList" ng-repeat="item in addressList"> 收货地址:<input type="address" name="address" ng-model="item.address"> <br /> </div>
那么它怎么取address的数据了。 login.addressList.address.$valid
还有一个属性是原生自带的,它叫name,也是最重要的一项,没有它一切验证都挂了。所以最重要的东西最后出场。name是angular和html关联的一个重要桥梁。所有的取值都是formName.inputFieldName。
表单验证里面最关心的就是错误那么angular对象下就有一个这样的错误对象。 formName.$error 整个表单里面所有的错误信息 formName.inputFieldName.$error 单个表单里面所有的错误信息 这个错误提示和验证指令有关。true就是错误,false就是正确。 formName.inputFieldName.$error.required 是否未填写 formName.inputFieldName.$error.minlength 是否小于最小长度 formName.inputFieldName.$error.maxlength 是否大于最大长度 formName.inputFieldName.$error.pattern 是否不符合正则表达式
以上就是angular表单相关基本都介绍完了,下面来说写一下和表单相关的问题和实践。
书接上回,基本指令,理论都介绍完了,那么接下该实战了。
ngModel来扩展更多功能
在项目中编写指令,常常会依赖其他的指令来实现想要达到的功能,其中最常用到的便是ng-model,它为我们明确了需要绑定的属性,虽然在指令中可以通过通过使用独立作用域的”=”来进行双向绑定,但使用ng-model更能简化指令的传值,符合angular的使用习惯。注意:使用ng-model就可以使用ng-change事件。
angular中编写自定义指令是通过require属性来指定查找依赖指令的controller,并传入link函数中进行调用.
.directive("...",function(){
return {
...
require:'^?ngModel',
link:function(scope,elem,attr,ngModelCtr){
...
}
...
}
})
require是angular指令一个依赖控制器,可以是一个字符串或者一个字符串数组
在查找指令的过程中,如果未找到指令,则会抛出一个编译错误。
可以通过加前缀来控制其查找的操作。
前缀 | 作用 |
---|---|
^ | 向上查找指令,未找到则报错 |
? | 未找到,取消报错,将null传到link的第四个参数 |
接来看几个实战栗子:
何为动态name,一般情况下name都是直接写死的,但是有一种情况,必须要写动态name,如果我们表单是不固定,通过ng-repeat循环添加的表单,这个时候你的input[name]可能是循环添加的,看下面栗子:
<div ng-form="addressList" ng-repeat="item in addressList">
收货地址:<input type="address" name="item.name" ng-model="item.address"> <br />
</div>
这个时候name无法解析的。你可能会想到,那用表达式呀,ok,想法不错。
<div ng-form="addressList" ng-repeat="item in addressList">
收货地址:<input type="address" name="{{item.name}}" ng-model="item.address"> <br />
</div>
这个时候,页面上解析是完全符合预期的,name=“address”,如果单纯的页面显示出来,就好了,那玩啥,我需要和angular关联,来验证我的表单,这是我重点。
我们在控制台打印控制器里面获取$scope对象,可以找到login这个对象,打开这个对象以后,会看到username,password,还有一个{{item.name}},等等,{{item.name}}是个什么鬼,我的预期的address去哪里的。
问题是{{item.name}}差值表达式,等angular运行完了,数据全部稳定了才开始解析,这个时候控制器里面已经绑定好了字段。这确实就是一个坑爹的事情了。那怎么办,angular好像也没有提供一个ng-name的玩意。没有那我们就自己动手撸一个my-name(自定义指令不用ng开头,这是行业约定吧。这个和angular机制有关系,指令就相当于在angular上面挂了一个方法,如果同名的就会出现后面覆盖前面,所以写指令最好有自己的命名空间加前缀)
angular
.module('myApp')
.directive('myName', function(){
return {
require: "ngModel",
link: function (scope, elm, iAttrs, ngModelCtr) {
ngModelCtr.$name = scope.$eval(iAttrs.cbName);
var formController = elm.controller('form') || {
$addControl: angular.noop
};
formController.$addControl(ngModelCtr);
scope.$on('$destroy', function () {
formController.$removeControl(ngModelCtr);
});
}
});
表单验证
表单验证,angular提供丰富的内置指令也很实用的指令,我们需要去使用它来做验证。唯一有个不足的地方,angular验证是边输入边验证,不是失去焦点验证。如果需要失去焦点验证需要自己去做些处理。后面回讲一些。
form标签
说到表单一定要说form标签,表单元素都是包裹在里面,我们写个表单以后,怎么和angular去关联。
拿常用一个简单登录页面来安利:
传统做法,获取login这个id,然后监听onsubmit事件,把username和password传给后台,需要验证username和password正确性,前端可以做一层简单拦截,用户体验一种,如果用户输入不是预期就给提示警告,直到正确为止,才让用户提交,当然后台也会做相同的验证。不是我们研究的重点。
使用angular.js该如何玩呢?
看到angular里面会出现一些奇怪东西。先不管奇怪的东西。我们来一一解释。
上面和我们验证有什么关系了。接着继续。。。
表单验证常用属性
表单对象 formName
formName就是我们上面栗子的form的name值
表单元素对象 inputfieldName
inputfieldName就是我们上面栗子的input的name值
如果我们需要访问username,就需要如此如此这般这般, login.username
表单元素常用的4个状态
未修改过的表单
布尔值属性,表示用户是否修改了表单。如果为ture,表示没有修改过;false表示修改过:
formName.inputFieldName.$pristine;
修改的表单
布尔型属性,当且仅当用户实际已经修改的表单。不管表单是否通过验证:
formName.inputFieldName.$dirty
经过验证的表单
布尔型属性,它指示表单是否通过验证。如果表单当前通过验证,他将为true:
formName.inputFieldName.$valid
未通过验证的表单
布尔值属性,表示用户没有通过验证。如果为ture,表示没有通过;false表示通过:
formName.inputFieldName.$invalid
同样这个这个状态也适用于formNam,回去看栗子submitForm(login.$valid)就是写的第三个,通过验证了才能提交。
常用的内置4个验证指令
那你肯定要问了这些状态根据什么判断,凭什么说我没有通过验证。下面就来说说说angular提交表单验证几个常用的指令。
以上4个是关于验证信息,来改变验证状态。
下面是几个常用的事件。