当模型数据在 angularjs 中的表单之外更改时,如何正确检查观察者中的表单有效性?
-
21-12-2019 - |
题
我对 AngularJS 还很陌生,我想我很难理解 $scope 的时间安排。在控制器中,我为绑定到各种表单元素的一些模型数据设置了一个观察器。当数据更改时,观察程序会触发 ajax 请求,除非表单无效。我正在使用 myForm.$valid 检查表单有效性。然而,这一切都非常简单,除非模型数据在控制器中更新,而不是在表单中更新。验证按预期运行,但 form.$valid 仍然具有以前的值,而不是更新后的数据应有的值。例如,如果表单以前有效,那么我删除绑定到所需输入的模型值,观察器将触发,因为模型数据已更改,但当我记录 myForm.$valid 的值时,它的值仍然为 true,即使它应该是假的。
所以我的问题是A。为什么会发生这种情况?但更重要的是 B.处理我想要完成的事情的正确方法是什么?自定义指令有意义吗?
这是一个简化的示例。
HTML:
<div ng-controller="MyCtrl">
<form name="myForm">
<input type="text" name="myField" ng-model="myData" required>
<button type="button" ng-click="myData=''">Delete</button>
</form>
<div>
The watcher says the form is: <strong>{{ formStatus }}</strong>
</div>
</div>
控制器:
myApp.controller('MyCtrl', ['$scope', function($scope) {
$scope.myData = 'abc';
$scope.formStatus = '';
$scope.$watch('myData', function(newVal, oldVal) {
if (newVal != oldVal) {
console.log("my data changed");
console.log("my form valid = ", $scope.myForm.$valid);
$scope.formStatus = $scope.myForm.$valid ? 'Valid' : 'Invalid';
}
});
}]);
解决方案
自定义指令是正确的方法。由于多种原因,通常建议将手表放入指令而不是控制器中。从较高层面来看,原因之一是 Angular 建议控制器精简,并且仅充当视图和服务之间的粘合剂。但你找到了一个具体的、有趣的原因。
控制器在链接 Angular 指令之前运行。因此,您的控制器监视会在 Angular 之前添加到监视列表中 ngModelWatch()
做为 myData
. ngModelWatch()
是 Angular 运行的地方 $formatters
(回想起来 $formatters
, 等,是模型发生更改时触发验证的地方)。
由于监视是按照添加到监视列表的顺序执行的,因此您的 控制器 $watch
在验证之前执行 正在被做 $formatters
.
如果你把同样的 $watch
在指令内,它将在链接期间添加 ngModelWatch()
已被添加到观察列表中。因此 该指令的 $watch
验证后会执行 已经完成了。
这是 更新的小提琴 您可以在其中查看执行顺序 $formatters
和每个 $watch
. 。你会看到指令版本按预期工作 - 之后运行 $formatters
.