在custom指令后运行$ watch

时间:2013-02-28 20:13:50

标签: angularjs

我正在编写一个自定义指令来验证范围中的某些值。它应该像所需的属性一样工作,但它不是验证输入文本,而是验证范围中的值。我的问题是这个值是在$ scope。$ watch函数中设置的,这个函数在我的指令之后运行。因此,当我的指令尝试验证它尚未设置的值时。是否可以在运行我的自定义指令之前运行$ watch代码?

以下是代码:

var app = angular.module('angularjs-starter', []);

app.controller('MainCtrl', function($scope) {
  var keys = {
    a: {},
    b: {}
  };
  $scope.data = {};

  // I need to execute this before the directive below
  $scope.$watch('data.objectId', function(newValue) {
    $scope.data.object = keys[newValue];
  });
});

app.directive('requiredAttribute', function (){ 
   return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
          var requiredAttribute = attr.requiredAttribute;
          ngModel.$parsers.unshift(function (value) {
             ngModel.$setValidity('requiredAttribute', scope[attr.requiredAttribute] != null);
             return value;
          });
      }
   };
});

<input type="text" name="objectId" ng-model="data.objectId" required-attribute="object" />
<span class="invalid" ng-show="myForm.objectId.$error.requiredAttribute">Key "{{data.objectId}}" not found</span>

这是一个吸血鬼:http://plnkr.co/edit/S2NrYj2AbxPqDrl5C8kQ?p=preview

感谢。

1 个答案:

答案 0 :(得分:1)

您可以直接在指令链接功能之前安排$watch。您需要更改link功能。

link: function(scope, elem, attr, ngModel) {
    var unwatch = scope.$watch(attr.requiredAttribute, function(requiredAttrValue) {
        if (requiredAttribute=== undefined) return;

        unwatch();

        ngModel.$parsers.unshift(function (value) {
            ngModel.$setValidity('requiredAttribute', requiredAttrValue != null);
            return value;
        });
    });
}

此方法仅激活指令内的$ watch函数一次,并在第一次设置所需范围变量时删除观察程序。

还有另一种方法可以解析值并以这种方式检查:

link: function(scope, elem, attr, ngModel) {
    var parsedAttr = $parse(attr.requiredAttribute);

    ngModel.$parsers.unshift(function (value) {
        ngModel.$setValidity('requiredAttribute', parsedAttr(scope) != null);
        return value;
    });
}

在这里,您需要使用$parse AngularJS服务。这里的区别在于,这将在不等待所需范围变量的第一个值集的情况下将输入字段标记为无效。

两种变体都允许您传递表达式而不是简单的变量名。这使得可以将内容写为required-attribute="object.var1.var2"

这实际上取决于你的需求。