[Angularjs]directive ngModelController
前言
最近在寫directive的時候,發現對ngModel掌握度較低,導致一些不明就理的問題,所以決心挖一下官網Api,然後較徹底的研究一下,所以就筆記一下。
$render
$viewValue是畫面上的值,$modelValue則是controller繫結的值,如果用了$render則不會自動binding,必須要自己指定值
<div ng-controller="mainCtrl as ctrl">
<form name="ctrl.form" ng-submit="ctrl.submit()" novalidate ng-model-options="{updateOn:'blur'}">
<input type="text" name="name" ng-model="ctrl.name" is-test required />
{{ctrl.name}}
<div ng-messages="ctrl.form.name.$error" ng-show="ctrl.form.name.$dirty" style="color:red">
<p ng-message="required">input is value</p>
</div>
</form>
</div>
</div>
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-messages.js"></script>
<script>
angular.module('app', ['ngMessages'])
.controller('mainCtrl', mainCtrl)
.directive('isTest', isTest);
function mainCtrl($http) {
var vm = this;
$http.get('http://localhost:51597/Api/Values').success(function (data) {
vm.name = data;
})
}
function isTest() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
ctrl.$render = function () {
elem.val("I am" + ctrl.$viewValue);
}
}
}
}
</script>
$parsers and $setValidity
$parsers.unshift可以在每次異動的時候觸發,$setValidity則可以自訂錯誤的訊息,裡面的needTwo則代表著自訂的ng-message裡面的錯誤名稱,如果回傳的是undefined的話,就是代表如果不符合的話,只會回傳空值。
function isTest() { return { restrict: 'A', require: '?ngModel', link: function (scope, elem, attrs, ctrl) { ctrl.$parsers.unshift(function (viewValue) { if (viewValue == 2) { ctrl.$setValidity('needTwo', true); //這個needTwo是代表自訂的錯誤名稱 return viewValue; } else { ctrl.$setValidity('needTwo', false); return undefined; } }) } } }
接著我們的ng-message就可以如下寫法,就可以驗証數字不是2的話,就驗證錯誤
<p ng-message="required">必填</p>
<p ng-message="needTwo">必須為2</p>
</div>
$validators
1.3之後支援更簡潔的方式,不過不能影響如果錯誤的話,要回傳的是什麼樣的值,預設就是空白值。
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
ctrl.$validators.needTwo = function (modelValue, viewValue) {
if (viewValue == 2) {
return true;
}
return false;
};
}
}
}
$asyncValidators
1.3之後同時支援$q的驗證錯誤,效能也更好,beOne代表的是自訂ng-message的名稱,只要是錯誤的話,model預設的就是空白值,像我這個例子只是在伺服器端判斷,必須為1才正確,否則回傳錯誤
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
ctrl.$asyncValidators.beOne = function (modelValue, viewValue) {
return $q(function (resolve, reject) {
$http.get('http://localhost:51597/Api/Values/' + viewValue).success(function () {
resolve();
}).error(function () {
reject();
})
})
}
}
}
}
$formatters
如果我們打算在一開始就要format要binding的值的話,也可以使用ngModel.$formatters.push的方式,比如說從api傳回來的日期,會是字串,這時候如果想要binding到html5的date,就會出現錯誤訊息(Error: [ngModel:datefmt] Expected `2015-10-17T17:11:23.2240502+08:00` to be a date),這時候就可以自訂directive如下例子
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elem, attrs, ctrl) {
ctrl.$formatters.push(function (value) {
return new Date(value);
})
}
}
}
改變控制項的狀態
代表著移除drity
ctrl.$setPristine();
代表設定為drity
ctrl.$setDirty();
設定為未碰觸過
Ctrl. $setUntouched();
設定為已碰觸過
Ctrl. $setTouched();
總結
希望對各位有幫助,如果有任何錯誤的話,再請多多指教