AngularJS : 当一个不同的元素改变时在指令中触发 $watch

AngularJS : Trigger $watch in directive when a different element changes

我在一个表单上有两个输入(field1field2)。 field1 有一个带有 $watch 的指令,而 field2 在控制器中有一个 $watchfield1 在添加一个值后显示 "This has a value" 或 "This field has no value" 或 added/removed。输入原始时消息为空白。

更改 field2 会将 field1 的值更改为空白。我想要发生的是通过触发指令中的 $watchfield1 显示 "This field has no value"。

我的项目实际上有更复杂的计算和跨多个输入的检查,但这是我需要做的基本要点。

笨蛋:http://plnkr.co/edit/XMdDt8M34VZJw1W0hkDt?p=preview

HTML:

<form name="myForm">
  <p>
    <label for="field1">Field 1</label>
    <input custom-validator name="field1" ng-model="item.field1" type="text" />
    <span>{{errorMessage}}</span>
  </p>
  <p>
    <label for="field2">Field 2</label>
    <input name="field2" ng-model="item.field2" type="text" />
  </p>
</form>

指令:

myApp.directive('customValidator', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attrs, ngModelCtrl) {
      scope.$watch(attrs.ngModel, function() {
        ngModelCtrl.$parsers.unshift(function(value) {
          if (value) {
            ngModelCtrl.$setValidity(ngModelCtrl.$name, false);
            scope.$parent.errorMessage = 'This field has a value.'
          } else {
            ngModelCtrl.$setValidity(ngModelCtrl.$name, true);
            scope.$parent.errorMessage = 'This field has no value.'
          }
        });
      });
    }
  }
});

控制器:

myApp.controller('FormController', function($scope) {
  $scope.item = {
    field1: '',
    field2: ''
  };

  $scope.$watch('item.field2', function(oldValue, newValue) {
    if (newValue) {
      $scope.item.field1 = '';
    }
  });
});

您需要向 $formatters pipiline 添加函数(因为您是从控制器而不是视图更改模型 - 然后 $parsers 工作)并且 运行 如果模型脏了:

myApp.directive('customValidator', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attrs, ngModelCtrl) {

            ngModelCtrl.$parsers.unshift(function(value) {
                if (value) {
                    ngModelCtrl.$setValidity(ngModelCtrl.$name, false);
                    scope.errorMessage = 'This field has a value.'
                } else {
                    ngModelCtrl.$setValidity(ngModelCtrl.$name, true);
                    scope.errorMessage = 'This field has no value.'
                }
            });

            ngModelCtrl.$formatters.unshift(function(value) {
                if (!value && ngModelCtrl.$dirty) {
                    ngModelCtrl.$setValidity(ngModelCtrl.$name, true);
                    scope.errorMessage = 'This field has no value.'
                }
            });
        }
    }
});

我还做了一些额外的更正。首先,删除 $parent 因为您的指令与错误消息共享相同的范围。然后我更改了 $watch 函数中的参数顺序:第一个是 newValue,第二个是 oldValue.

演示: http://plnkr.co/edit/VXpsrhvYliW9ICtFsdY6?p=preview