要求新/隔离范围的多个指令[arValidations,datepickerPopup]

时间:2015-04-14 19:46:53

标签: angularjs angularjs-directive angularjs-scope

尝试将自定义指令与datepicker结合使用时出现以下错误:

Multiple directives [arValidations, datepickerPopup] asking for new/isolated scope on...

所以我想我需要删除孤立的范围,问题是我不知道如何。这是我的指示:

app.directive('arValidations', [ 'BaseValidator', '$injector', function(BaseValidator, $injector){
  return {
    restrict: 'A',
    scope: { arValidations: '@?' },
    require: '?ngModel',
    link: function(scope, element, attrs, ngModel){

      scope.validations = JSON.parse(scope.arValidations);
      scope.Validator = $injector.get(scope.validations.validator);
      scope.pristine = true;

      scope.BaseValidator = BaseValidator;
      scope.$watch(function(){ return ngModel.$modelValue }, function (attr) {

        var label = scope.validations["attribute"];
        var types = scope.Validator.attributes[label].types;
        var validated = scope.BaseValidator.validateValue(types, attr);

        scope.Validator.attributes[label].valid = validated === true && scope.pristine === false;
        scope.Validator.allValid = scope.BaseValidator.updateAllValidations(scope.Validator.attributes);

        scope.pristine = false;

        if(scope.Validator.attributes[label].valid){
          element.removeClass('valid-input');
          element.addClass('valid-input');
        } else{
          element.removeClass('valid-input');
        }
      });
    }
  }
}]);

主要问题是我在该指令的每个实例中注入了不同的服务。有什么建议吗?

编辑:我在评论中多次说过,但使用arValidations获取attrs属性而不是隔离范围不提供相同的功能,因为同一指令的多个实例可以在同一范围内创建,覆盖scope.Validator

的内容

解决方案是将2个指令分成几个元素以保持范围隔离。所以这是我今天的作业:

指令:

app.directive('validatedDatepicker',  function(){
  return {
    templateUrl: 'directives/validated_datepicker.html',
    scope: { modelInstance: '=validatedDatepicker', modelAttribute: '@?', placeholder: '@?', maxDate: '=?' },
    controller: ['$scope', 'BaseValidator', '$injector', function($scope, BaseValidator, $injector){
      $scope.cssClass = { 'valid-input':  false };
      $scope.Validator = $injector.get($scope.modelInstance.$validator);
      $scope.pristine = true;

      $scope.BaseValidator = BaseValidator;
      $scope.calendarDisplay = false;

      $scope.openDate = function(e){
        e.preventDefault();
        e.stopPropagation();
        $scope.calendarDisplay = true;
      };

      $scope.$watch(function(){ return $scope.modelInstance[$scope.modelAttribute]; }, function (attr) {

        var label = $scope.modelAttribute;
        var types = $scope.Validator.attributes[label].types;

        var validated = $scope.BaseValidator.validateValue(types, attr);

        $scope.Validator.attributes[label].valid = validated === true && $scope.pristine === false;
        $scope.Validator.allValid = $scope.BaseValidator.updateAllValidations($scope.Validator.attributes);

        $scope.pristine = false;

        if($scope.Validator.attributes[label].valid){
          $scope.cssClass = { 'valid-input':  true };

        } else{
          $scope.cssClass = { 'valid-input':  false };
        }
      });
    }]
  }
});

模板:

<input placeholder="{{placeholder}}" ng-class="cssClass" type="text" show-button-bar="false" class="form-control required-input" datepicker-popup="dd-MM-yyyy" data-ng-model="modelInstance[modelAttribute]" max-date="modelInstance[maxDate]" is-open="calendarDisplay" close-text="Close"/>
<div class="input-group-addon" data-ng-click="openDate($event)"><i class="fa fa-calendar"></i></div>

编辑2:为了完整性,scope: true会出现与scope: {}相同的错误。

1 个答案:

答案 0 :(得分:0)

如果arValidations应该与相同元素上的其他指令一起使用(我认为是这种情况),那么应该创建一个隔离的范围,而是共享与其他指令的范围相同。

因此,您要删除行scope: { arValidations: '@?' }

但是现在您需要以常规方式手动实施此@绑定,方法是在link函数中添加:

attrs.$observe('arValidations', function(value) {
  scope.arValidations = value;
});

这样,每次更新{{}}插值绑定时,都会更新范围。

更新为了让您的直接拥有自己的范围,但仍然继承并且不是孤立的,您需要将scope: true添加到指令中:

restrict: 'A',
scope: true,
require: '?ngModel',
link: ....