我正在编写一个带有自定义验证逻辑的指令来验证对象。
HTML:
<input type="hidden" name="obj" ng-model="vm.obj" validate-object />
JS:
angular
.module('myApp')
.directive('validateObject', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
ngModelCtrl.$validators.validateObject = myValidator;
function myValidator (modelValue, viewValue) {
return validateObject(modelValue);
}
function validateObject (obj) {
// Look inside the object
}
}
}
});
问题是当对象内的属性发生更改时,验证程序不会运行。
我可以使用$watch
添加objectEquality === true
,然后使用我的验证逻辑手动$setCustomValidity
。像这样:
link: function (scope, element, attrs, ngModelCtrl) {
scope.$watch(attrs.ngModel, onModelChange, true);
function onModelChange (newValue) {
ngModelCtrl.$setCustomValidity('validateObject', validateObject(newValue))
}
function validateObject (obj) {
// Look inside the object
}
}
但我不喜欢使用旧学校的方式手动使用$setValidity
,另外添加手册$watch
,而NgModelController
已经有了在更新过程中注册的方法(如{ {1}}),此外$formatters
是一个可能存在性能问题的深层问题。
我错了吗?还有更好的方法吗?
答案 0 :(得分:2)
来自https://github.com/angular/angular.js/blob/master/src/ng/directive/ngModel.js#L699:
if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
return;
}
ngModel对旧版本的模型执行平面相等检查,因此对象内的任何更改都不会反映在ngModel或ngChange上。
优化方法是使用不可变数据,这意味着每次更改模型(对象)时,都要创建一个新副本:
function changeModel(){
this.vm.name = "roy";
// Create a new object for ngModel;
this.vm = angular.copy(this.vm);
}
修改强>
我记得我以前解决了以前的问题。您希望将一组ng-model绑定到对象的属性,并为整个对象设置1个更改侦听器。
这是我的解决方案:http://plnkr.co/edit/6tPMrB8n1agINMo252F2?p=preview
我所做的是创建一个必须放在表单元素上的新指令“formModel”。 Angular有一个带有控制器的form指令。 NgModelController需要一个父表单控制器,然后它将自己添加到表单中(这就是你在整个表单上获得有效性的方式)。 所以在我的指令中,我修饰了表单的$ addControl方法,并为每个通过$ viewChangeListeners添加自己的ngModelController添加了一个监听器,现在在表单内的每次更改ngModel时,formModel指令将复制整个对象并触发$ setViewValue