我对 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';
        }
    });
}]);

小提琴: http://jsfiddle.net/anpsince83/cK6cc/1/

有帮助吗?

解决方案

自定义指令是正确的方法。由于多种原因,通常建议将手表放入指令而不是控制器中。从较高层面来看,原因之一是 Angular 建议控制器精简,并且仅充当视图和服务之间的粘合剂。但你找到了一个具体的、有趣的原因。

控制器在链接 Angular 指令之前运行。因此,您的控制器监视会在 Angular 之前添加到监视列表中 ngModelWatch() 做为 myData. ngModelWatch() 是 Angular 运行的地方 $formatters (回想起来 $formatters, 等,是模型发生更改时触发验证的地方)。

由于监视是按照添加到监视列表的顺序执行的,因此您的 控制器 $watch 在验证之前执行 正在被做 $formatters.

如果你把同样的 $watch 在指令内,它将在链接期间添加 ngModelWatch() 已被添加到观察列表中。因此 该指令的 $watch 验证后会执行 已经完成了。

这是 更新的小提琴 您可以在其中查看执行顺序 $formatters 和每个 $watch. 。你会看到指令版本按预期工作 - 之后运行 $formatters.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top