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

Javascript 在angularjs中,当模型数据在表单之外更改时,如何在观察者内正确检查表单有效性?,javascript,validation,angularjs,angularjs-scope,angularjs-ng-form,Javascript,Validation,Angularjs,Angularjs Scope,Angularjs Ng Form,我对AngularJS还是一个新手,我想我很难理解$scope的时间安排。在控制器中,我为绑定到各种表单元素的一些模型数据设置了一个监视程序。当数据发生变化时,观察者会发出ajax请求,除非表单无效。我正在用我的表格检查表格的有效性。$valid。但是,这是非常简单的,除非在控制器中更新模型数据,而不是表单中。验证按预期运行,但form.$valid仍具有以前的值,而不是更新数据时的值。例如,如果表单以前是有效的,那么我删除绑定到所需输入的模型值,监视程序将触发,因为模型数据已更改,但当我记录m

我对AngularJS还是一个新手,我想我很难理解$scope的时间安排。在控制器中,我为绑定到各种表单元素的一些模型数据设置了一个监视程序。当数据发生变化时,观察者会发出ajax请求,除非表单无效。我正在用我的表格检查表格的有效性。$valid。但是,这是非常简单的,除非在控制器中更新模型数据,而不是表单中。验证按预期运行,但form.$valid仍具有以前的值,而不是更新数据时的值。例如,如果表单以前是有效的,那么我删除绑定到所需输入的模型值,监视程序将触发,因为模型数据已更改,但当我记录myForm的值时,$valid它的值仍然为true,即使它应该为false

所以我的问题是A。为什么会发生这种情况?但更重要的是B。什么是正确的方式来处理我试图完成的事情?自定义指令有意义吗

这里是一个简化的例子

HTML:


Fiddle:

自定义指令是正确的选择。出于几个原因,通常建议将手表放在指令和控制器中。从高层次上讲,一个原因是控制器很薄,只能作为视图和服务之间的粘合剂进行操作。但你找到了一个特别有趣的原因

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

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

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


在这里,您可以查看
$formatters
和每个
$watch
的执行顺序。您将看到指令版本按预期工作-在
$formatters

之后运行似乎正常。这与您期望的相符吗?将手表放在
$valid
本身是您的选择吗?像这样:嗯,小提琴肯定能用。在我的应用程序中,我有一个更复杂的嵌套表单设置,我想知道这是否与此有关。观看$valid可能是一个选项,理想情况下,我希望能够观察模型数据并理解为什么$valid在观察程序中没有返回正确的值。似乎在这种嵌套形式下也能工作:感谢您的清晰解释和更新的fiddle!这正是我想要的。
<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';
        }
    });
}]);