AngularJS 预定义的 FormController
前面的“表单控制”那章,实际上讲的就是 FormController ,只是那里是从 scope
中获取到的引用。现在从指令定义的角度,来更清楚地了解 FormController 及 NgModelController 是如何配合工作的。
先说一下, form 和 ngForm 是官方定义的两个指令,但是它们其实是同一个东西。前者只允许以标签形式使用,而后者允许 EAC
的形式。DOM 结构中, form
标签不能嵌套,但是 ng 的指令没有这个限制。不管是 form 还是 ngForm ,它们的 controller
都被命名成了 form
。 所以 require 这个参数不要写错了。
FormController 的几个成员是很好理解的:
- $pristine 表单是否被动过
- $dirty 表单是否没被动过
- $valid 表单是否检验通过
- $invalid 表单是否检验未通过
- $error 表单中的错误
- $setDirty() 直接设置 $dirty 及 $pristine
<div ng-controller="TestCtrl"> <div ng-form test> <input ng-model="a" type="email" /> <button ng-click="do()">查看</button> </div> </div>
var app = angular.module('Demo', [], angular.noop); app.directive('test', function(){ var link = function($scope, $element, $attrs, $ctrl){ $scope.do = function(){ //$ctrl.$setDirty(); console.log($ctrl.$pristine); //form是否没被动过 console.log($ctrl.$dirty); //form是否被动过 console.log($ctrl.$valid); //form是否被检验通过 console.log($ctrl.$invalid); //form是否有错误 console.log($ctrl.$error); //form中有错误的字段 } } return {compile: function(){return link}, require: 'form', restrict: 'A'} }); app.controller('TestCtrl', function($scope){ });
$error 这个属性,是一个对象, key
是错误名, value
部分是一个列表,其成员是对应的 NgModelController 的实例。
FormController 可以自由增减它包含的那些,类似于 NgModelController 的实例。在 DOM 结构上,有 ng-model
的 input
节点的 NgMoelController 会被自动添加。
- $addControl() 添加一个 conroller
- $removeControl() 删除一个 controller
这两个手动使用机会应该不会很多。被添加的实例也可以手动实现所有的 NgModelController的方法
<div ng-controller="TestCtrl"> <bb /> <div ng-form test> <input ng-model="a" type="email" /> <button ng-click="add()">添加</button> </div> </div>
var app = angular.module('Demo', [], angular.noop); app.directive('test', function(){ var link = function($scope, $element, $attrs, $ctrl){ $scope.add = function(){ $ctrl.$addControl($scope.bb); console.log($ctrl); } } return {compile: function(){return link}, require: 'form', restrict: 'A'} }); app.directive('bb', function(){ var controller = function($scope, $element, $attrs, $transclude){ $scope.bb = this; this.$name = 'bb'; } return {compile: angular.noop, restrict: 'E', controller: controller} }); app.controller('TestCtrl', function($scope){ });
整合 FormController 和 NgModelController 就很容易扩展各种类型的字段:
<div ng-controller="TestCtrl"> <form name="f"> <input type="my" ng-model="a" /> <button ng-click="show()">查看</button> </form> </div>
var app = angular.module('Demo', [], angular.noop); app.directive('input', function(){ var link = function($scope, $element, $attrs, $ctrl){ console.log($attrs.type); var validator = function(v){ if(v == '123'){ $ctrl.$setValidity('my', true); return v; } else { $ctrl.$setValidity('my', false); return undefined; } } $ctrl.$formatters.push(validator); $ctrl.$parsers.push(validator); } return {compile: function(){return link}, require: 'ngModel', restrict: 'E'} }); app.controller('TestCtrl', function($scope){ $scope.show = function(){ console.log($scope.f); } });
虽然官方原来定义了几种 type
,但这不妨碍我们继续扩展新的类型。如果新的 type
参数值不在官方的定义列表里,那会按 text
类型先做处理,这其实什么影响都没有。剩下的,就是写我们自己的验证逻辑就行了。
上面的代码是参见官方的做法,使用格式化的过程,同时在里面做有效性检查。
更多建议: