加载中...

预定义的 FormController


18.11. 预定义的 FormController

前面的“表单控制”那章,实际上讲的就是 FormController ,只是那里是从 scope 中获取到的引用。现在从指令定义的角度,来更清楚地了解 FormControllerNgModelController 是如何配合工作的。

先说一下, formngForm 是官方定义的两个指令,但是它们其实是同一个东西。前者只允许以标签形式使用,而后者允许 EAC 的形式。DOM 结构中, form 标签不能嵌套,但是 ng 的指令没有这个限制。不管是 form 还是 ngForm ,它们的 controller 都被命名成了 form 。 所以 require 这个参数不要写错了。

FormController 的几个成员是很好理解的:

$pristine 表单是否被动过$dirty 表单是否没被动过$valid 表单是否检验通过$invalid 表单是否检验未通过$error 表单中的错误$setDirty() 直接设置 $dirty$pristine

查看
  1. var app = angular.module('Demo', [], angular.noop);
  2. app.directive('test', function(){
  3. var link = function($scope, $element, $attrs, $ctrl){
  4. $scope.do = function(){
  5. //$ctrl.$setDirty();
  6. console.log($ctrl.$pristine); //form是否没被动过
  7. console.log($ctrl.$dirty); //form是否被动过
  8. console.log($ctrl.$valid); //form是否被检验通过
  9. console.log($ctrl.$invalid); //form是否有错误
  10. console.log($ctrl.$error); //form中有错误的字段
  11. }
  12. }
  13. return {compile: function(){return link},
  14. require: 'form',
  15. restrict: 'A'}
  16. });
  17. app.controller('TestCtrl', function($scope){
  18. });

$error 这个属性,是一个对象, key 是错误名, value 部分是一个列表,其成员是对应的 NgModelController 的实例。

FormController 可以自由增减它包含的那些,类似于 NgModelController 的实例。在 DOM 结构上,有 ng-modelinput 节点的 NgMoelController 会被自动添加。

$addControl() 添加一个 conroller $removeControl() 删除一个 controller
这两个手动使用机会应该不会很多。被添加的实例也可以手动实现所有的 NgModelController 的方法

  1. <div ng-controller="TestCtrl">
  2. <bb />
  3. <div ng-form test>
  4. <input ng-model="a" type="email" />
  5. <button ng-click="add()">添加</button>
  6. </div>
  7. </div>
  8. 1 var app = angular.module('Demo', [], angular.noop);
  9. 2 3 app.directive('test', function(){
  10. 4 var link = function($scope, $element, $attrs, $ctrl){
  11. 5 $scope.add = function(){
  12. 6 $ctrl.$addControl($scope.bb);
  13. 7 console.log($ctrl);
  14. 8 }
  15. 9 }
  16. 1011 return {compile: function(){return link},
  17. 12 require: 'form',
  18. 13 restrict: 'A'}
  19. 14 });
  20. 1516 app.directive('bb', function(){
  21. 17 var controller = function($scope, $element, $attrs, $transclude){
  22. 18 $scope.bb = this;
  23. 19 this.$name = 'bb';
  24. 20 }
  25. 2122 return {compile: angular.noop,
  26. 23 restrict: 'E',
  27. 24 controller: controller}
  28. 25 });
  29. 2627 app.controller('TestCtrl', function($scope){
  30. 28 });

整合 FormControllerNgModelController 就很容易扩展各种类型的字段:

  1. <div ng-controller="TestCtrl">
  2. <form name="f">
  3. <input type="my" ng-model="a" />
  4. <button ng-click="show()">查看</button>
  5. </form>
  6. </div>
  7. 1 var app = angular.module('Demo', [], angular.noop);
  8. 2 3 app.directive('input', function(){
  9. 4 var link = function($scope, $element, $attrs, $ctrl){
  10. 5 console.log($attrs.type);
  11. 6 var validator = function(v){
  12. 7 if(v == '123'){
  13. 8 $ctrl.$setValidity('my', true);
  14. 9 return v;
  15. 10 } else {
  16. 11 $ctrl.$setValidity('my', false);
  17. 12 return undefined;
  18. 13 }
  19. 14 }
  20. 1516 $ctrl.$formatters.push(validator);
  21. 17 $ctrl.$parsers.push(validator);
  22. 18 }
  23. 1920 return {compile: function(){return link},
  24. 21 require: 'ngModel',
  25. 22 restrict: 'E'}
  26. 23 });
  27. 2425 app.controller('TestCtrl', function($scope){
  28. 26 $scope.show = function(){
  29. 27 console.log($scope.f);
  30. 28 }
  31. 29 });

虽然官方原来定义了几种 type ,但这不妨碍我们继续扩展新的类型。如果新的 type 参数值不在官方的定义列表里,那会按 text 类型先做处理,这其实什么影响都没有。剩下的,就是写我们自己的验证逻辑就行了。

上面的代码是参见官方的做法,使用格式化的过程,同时在里面做有效性检查。


还没有评论.