前面的“表單控制”那章,實際上講的就是 FormController ,只是那里是從 scope
中獲取到的引用?,F(xiàn)在從指令定義的角度,來更清楚地了解 FormController 及 NgModelController 是如何配合工作的。
先說一下, form 和 ngForm 是官方定義的兩個指令,但是它們其實是同一個東西。前者只允許以標簽形式使用,而后者允許 EAC
的形式。DOM 結構中, form
標簽不能嵌套,但是 ng 的指令沒有這個限制。不管是 form 還是 ngForm ,它們的 controller
都被命名成了 form
。 所以 require 這個參數(shù)不要寫錯了。
FormController 的幾個成員是很好理解的:
<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
節(jié)點的 NgMoelController 會被自動添加。
這兩個手動使用機會應該不會很多。被添加的實例也可以手動實現(xiàn)所有的 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
,但這不妨礙我們繼續(xù)擴展新的類型。如果新的 type
參數(shù)值不在官方的定義列表里,那會按 text
類型先做處理,這其實什么影響都沒有。剩下的,就是寫我們自己的驗證邏輯就行了。
上面的代碼是參見官方的做法,使用格式化的過程,同時在里面做有效性檢查。
更多建議: