为什么 ngModel 验证器代码似乎在 scope.$watch 更改之前 运行?

Why does the ngModel validator code seem to run before the scope.$watch changes?

我正在尝试使用自定义验证器创建一个 AngularJS 指令,以便我可以根据验证器显示错误消息。但是,我 运行ning 出错了,因为根据我输入的 console.log() 消息,验证器似乎在范围之前 运行ning。$watch() 。

指令如下:

angular
  .module('app')
  .directive('validateRefundAmount', validateRefundAmount);
validateRefundAmount.$inject = [ 'AmountConversionService', '$q' ];

function validateRefundAmount(AmountConversionService, $q) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, control) {
      scope.$watch('orderDetails.refundAmount', function(newValue, oldValue) {
        if (newValue === oldValue) {
          console.log(newValue, oldValue);
          return;
        }
        
        // Get Already Refunded Amount
        var refundedAmount = scope.orderDetails.refundedAmount;

        // Converts Amount To Pure Integers, Removing Decimal
        var totalPaymentAmount = AmountConversionService.prepareAmountForCalculations(scope.orderDetails.paymentAmount, 10);
        var totalRefundAmount = AmountConversionService.prepareAmountForCalculations(newValue || 0);

        // Add Already Refunded Amount to Previously Refunded Amount to Get Total Refund
        if (refundedAmount) {
          totalRefundAmount += AmountConversionService.prepareAmountForCalculations(refundedAmount);
        }

        control.$validators.refundAmountTooHigh = function() {
          if (totalRefundAmount > totalPaymentAmount) {
            return false
          } 
          return true;
        }
     });
    }
  };
}

应用的元素是一个没有值开头的文本输入框。当我在字段中键入“1”时,验证器不会 运行。当我在字段中添加一个“2”,生成“12”时,验证器 运行s 将“1”作为输入。当我将“3”添加到字段“123”时,也会发生同样的事情——它 运行s 为“12”,而不是新值“123”。

当我插入 console.log() 语句以查看发生了什么时,它看起来像验证程序代码 运行s 然后 scope.watch() 运行s 在验证器 运行 之后创建新值,但我不知道为什么或要搜索什么才能找到答案。

可能还有另一种方法可以做我想做的事情——我想做的是 运行 每次元素值改变时验证器。由于按键未检测到退格键,我无法在按键上使用绑定,也许可以在按键上使用绑定——不确定。

请检查 $setViewValue 的文档,显然在 ngModelValue 更新之前使用了 $validators。

你的范围。$watch 只会在 $modelValue 更新后被调用。

https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#$setViewValue

调用 $setViewValue 时,将暂存新值以通过 $parsers 和 $validators 管道提交。如果没有指定特殊的 ngModelOptions 则暂存值将直接发送以通过 $parsers 管道进行处理。 之后,调用 $validators 和 $asyncValidators 并将值应用于 $modelValue。最后,该值设置为 ng-model 属性中指定的表达式,并调用 $viewChangeListeners 列表中所有已注册的更改侦听器。