我还是AngularJS的新手,我觉得我无法理解$ scope的时机。在控制器中,我为一些绑定到各种表单元素的模型数据设置了一个观察器。当数据发生变化时,观察者会触发ajax请求,除非表单无效。我正在使用myForm检查表单有效性。$ valid。然而,这一切都非常简单,除非在控制器中更新模型数据,而不是表单。验证按预期运行,但是表单。$ 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';
}
});
}]);
答案 0 :(得分:3)
自定义指令是正确的方法。一般建议将手表放在指令与控制器之间。在较高的层面上,一个原因是Angular建议控制器很薄,只能作为视图和服务之间的粘合剂。但是你有一个特定的,有趣的原因。
控制器在Angular指令链接之前运行。因此,在Angular的ngModelWatch()
为myData
之前,您的控制器监视会被添加到监视列表中。 ngModelWatch()
是Angular运行$formatters
的地方(回想起$formatters
,其中包括模型发生更改时触发验证的地方)。
由于手表按照添加到观察列表的顺序执行,因此控制器$watch
会在$formatters
完成验证之前执行。
如果您将相同的$watch
放在指令中,则会在ngModelWatch()
添加到监视列表后的链接中添加它。因此指令的$watch
将在验证完成后执行。。
以下是an updated fiddle,您可以在其中查看$formatters
和每个$watch
的执行顺序。并且您将看到指令版本按预期工作 - 在$formatters
之后运行。