当在angularjs中更改模型数据时,如何在观察者中正确检查表单有效性?

时间:2014-01-10 01:15:01

标签: javascript validation angularjs angularjs-scope angularjs-ng-form

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

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

1 个答案:

答案 0 :(得分:3)

自定义指令是正确的方法。一般建议将手表放在指令与控制器之间。在较高的层面上,一个原因是Angular建议控制器很薄,只能作为视图和服务之间的粘合剂。但是你有一个特定的,有趣的原因。

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

由于手表按照添加到观察列表的顺序执行,因此控制器$watch会在$formatters完成验证之前执行

如果您将相同的$watch放在指令中,则会在ngModelWatch()添加到监视列表后的链接中添加它。因此指令的$watch将在验证完成后执行。

以下是an updated fiddle,您可以在其中查看$formatters和每个$watch的执行顺序。并且您将看到指令版本按预期工作 - 在$formatters之后运行。