预定义的 FormController

最后更新于:2022-04-01 22:40:49

### 18.11. 预定义的 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_
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_ 的方法
1 var app = angular.module('Demo', [], angular.noop); 2 3 app.directive('test', function(){ 4 var link = function($scope, $element, $attrs, $ctrl){ 5 $scope.add = function(){ 6 $ctrl.$addControl($scope.bb); 7 console.log($ctrl); 8 } 9 } 1011 return {compile: function(){return link}, 12 require: 'form', 13 restrict: 'A'} 14 }); 1516 app.directive('bb', function(){ 17 var controller = function($scope, $element, $attrs, $transclude){ 18 $scope.bb = this; 19 this.$name = 'bb'; 20 } 2122 return {compile: angular.noop, 23 restrict: 'E', 24 controller: controller} 25 }); 2627 app.controller('TestCtrl', function($scope){ 28 }); 整合 _FormController_ 和 _NgModelController_ 就很容易扩展各种类型的字段:
1 var app = angular.module('Demo', [], angular.noop); 2 3 app.directive('input', function(){ 4 var link = function($scope, $element, $attrs, $ctrl){ 5 console.log($attrs.type); 6 var validator = function(v){ 7 if(v == '123'){ 8 $ctrl.$setValidity('my', true); 9 return v; 10 } else { 11 $ctrl.$setValidity('my', false); 12 return undefined; 13 } 14 } 1516 $ctrl.$formatters.push(validator); 17 $ctrl.$parsers.push(validator); 18 } 1920 return {compile: function(){return link}, 21 require: 'ngModel', 22 restrict: 'E'} 23 }); 2425 app.controller('TestCtrl', function($scope){ 26 $scope.show = function(){ 27 console.log($scope.f); 28 } 29 }); 虽然官方原来定义了几种 `type` ,但这不妨碍我们继续扩展新的类型。如果新的 `type` 参数值不在官方的定义列表里,那会按 `text` 类型先做处理,这其实什么影响都没有。剩下的,就是写我们自己的验证逻辑就行了。 上面的代码是参见官方的做法,使用格式化的过程,同时在里面做有效性检查。
';