【问题标题】:AngularJS Custom Validation Directives - How to avoid using isolated scopeAngularJS 自定义验证指令 - 如何避免使用隔离范围
【发布时间】:2017-12-27 06:58:44
【问题描述】:

我正在尝试在文本字段上使用多个角度验证器,但遇到了 Multiple directives requesting isolated scope 错误。 (请在关闭之前继续阅读。)

到目前为止,我看到的所有解决方案都建议从违规指令中删除 scope: {...},但是对于我的场景,我需要评估来自控制器的变量(以及 $watch 它们以进行更改)。

我尝试过使用attrs.$observe,但我不知道如何将评估变量 放入$validator 函数中。 (另外,我不能$observengModel)。

如果有其他方法可以解决此问题,请告诉我。

这是我能整理的最小的例子。 注意 maxLength 验证器的作用域已被注释掉,实际上是禁用它:

angular

.module('app', [])

// validates the min length of a string...
.directive("minLen", function() {
    return {
      require: 'ngModel',
      restrict: 'A',
      scope: {
        ngModel: '=',
        minLen: '='
      },
      link: function(scope, element, attrs, ngModelCtrl) {
        scope.$watch('ngModel', function(){
          ngModelCtrl.$validate();
        });
        scope.$watch('minLen', function(){
          ngModelCtrl.$validate();
        });
        ngModelCtrl.$validators.minLength = function(modelValue, viewValue) {
          var value = modelValue || viewValue;
          return angular.isUndefined(scope.minLen) ||
            angular.isUndefined(value) ||
            value.length >= scope.minLen;
        };
      }
	};
})

.directive("maxLen", function() {
    return {
      require: 'ngModel',
      restrict: 'A',
// Commented out for now - causes error.      
//       scope: {
//         ngModel: '=',
//         maxLen: "="
//       },
      link: function(scope, element, attrs, ngModelCtrl) {
        scope.$watch('ngModel', function(){
          ngModelCtrl.$validate();
        });
        scope.$watch('maxLen', function(){
          ngModelCtrl.$validate();
        });
        ngModelCtrl.$validators.maxLength = function(modelValue, viewValue) {
          var value = modelValue || viewValue;
          return angular.isUndefined(scope.maxLen) ||
            angular.isUndefined(value) ||
            value.length >= scope.maxLen;
        };
      }
	};
})

// this controller just initialises variables...
.controller('CustomController', function() {
  var vm = this;
  vm.toggleText = function(){
    if (vm.text === 'aaa') {
      vm.text = 'bbbbb';
    } else {
      vm.text = 'aaa';
    }
  }
  vm.toggle = function(){
    if (vm.minLen === 3) {
      vm.minLen = 4;
      vm.maxLen = 12;
    } else {
      vm.minLen = 3;
      vm.maxLen = 10;
    }
  };
  vm.toggleText();
  vm.toggle();
  return vm;
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-controller="CustomController as ctrl">
  <ng-form name="ctrl.form">
    <label>Enter {{ctrl.minLen}}-{{ctrl.maxLen}} characters: </label>
    <input 
           name="text" 
           type="text" 
           ng-model="ctrl.text" 
           min-len="ctrl.minLen"
           max-len="ctrl.maxLen"
           />
  </ng-form>
  <br/><br/>
  <button ng-click="ctrl.toggle()">Modify validation lengths</button>
  <button ng-click="ctrl.toggleText()">Modify ngModel (text)</button>
  
  <h3>Validation (just list $error for now)</h3>
  <pre>{{ ctrl.form.text.$error | json }}</pre>
</div>

【问题讨论】:

  • 你为什么不使用ng-maxlengthng-minlength指令?
  • @georgeawg - 因为我试图将其归结为最简单的示例。我的真实示例是“深度”验证对象数组。

标签: angularjs validation angularjs-directive angularjs-ng-model


【解决方案1】:
  1. 移除隔离作用域
  2. 您不需要观察,观察 ngModel - 当它发生变化时,Angular 将为您运行验证器。
  3. 决定如何使用指令:my-val-dir="{{valName}}" vs my-val-dir="valName"。在第一种情况下,您使用 attrs.$observe('myValDir'),在第二种情况下使用 $watch(attrs.myValDir) 和 $eval。 当你的值很简单时,比如数字或短字符串 - 第一种方法看起来不错,当值很大时,即数组 - 使用第二种方法。

【讨论】:

    【解决方案2】:

    移除隔离范围并使用scope.$watch 评估属性:

    app.directive("minLen", function() {
        return {
          require: 'ngModel',
          restrict: 'A',
          scope: false,
       //     ngModel: '=',
       //     minLen: '='
       //   },
          link: function(scope, element, attrs, ngModelCtrl) {
            var minLen = 0;
            scope.$watch(attrs.minLen, function(value){
              minLen = toInt(value) || 0;
              ngModelCtrl.$validate();
            });
            ngModelCtrl.$validators.minLength = function(modelValue, viewValue) {
              return ngModelCtrl.$isEmpty(viewValue) || viewValue.length >= minLen;
            };
          }
        };
    })
    

    无需关注ngModel 属性,因为ngModelController 会在模型更改时自动调用$validators 集合中的函数。

    当监视表达式是字符串时,字符串属性将被评估为Angular Expression

    有关详细信息,请参阅AngularJS scope API Reference - $watch

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多