2013-02-28 77 views
0

我正在编写自定义指令来验证作用域中的某个值。它应该像所需的属性一样工作,但不是验证输入文本,而是验证范围中的值。我的问题是这个值设置在$ 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> 

这里是一个plunker:http://plnkr.co/edit/S2NrYj2AbxPqDrl5C8kQ?p=preview

感谢。

回答

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; 
     }); 
    }); 
} 

这种方法将激活指令里面的$腕表功能只有一次,将删除观察者第一次您所需要的范围变量。

还有,你分析的价值,并检查它这样另一种方法:

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"

这真的取决于你需要什么。