$ observe不会触发更改而不是插值

时间:2016-08-05 14:17:31

标签: angularjs validation

TLDR:为什么angular的ngMinlength接收带有插值的$ observe更新,但是我的自定义验证指令没有?

Link to plnkr

我正在研究Angular 1.3中的自定义验证指令,并注意到一些似乎不一致的东西。 angular中的指令似乎从attr。$ observe获得插值更新,但我创建的指令的行为方式不同。

我可以使用$ watch来修复它,或绑定插值,但与现有的验证指令不一致。有什么区别,我如何让我的自定义指令与内置验证指令类似?

Angular的指令

var minlengthDirective = function() {
        return {
          restrict: 'A',
          require: '?ngModel',
          link: function(scope, elm, attr, ctrl) {
            if (!ctrl) return;

            var minlength = 0;
            attr.$observe('minlength', function(value) {
              minlength = int(value) || 0;
              ctrl.$validate();
            });
            ctrl.$validators.minlength = function(modelValue, viewValue) {
              return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
            };
          }
        };
      };

我的指示

function observeMinLength($log){
  return {
      restrict: 'A',
      require: '?ngModel',
      link: function (scope, elm, attr, ctrl) {
          if (!ctrl) return;

          var min;

          //Problem 1: observered value is not interpolated
          //Problem 2: observe  is only fired one time
          attr.$observe('observeMinlength', function (value) {
              $log.debug('observed value: ' + value);
              min = parseInt(value, 10) || 0;
              ctrl.$validate();
          });

          ctrl.$validators.mymin = function (modelValue, viewValue) {
            var len = 0;
            if (viewValue){
              len = viewValue.length;
            }
            return ctrl.$isEmpty(viewValue) || viewValue.length >= min;
          };
      }
  };
}

1 个答案:

答案 0 :(得分:0)

请注意,ngMinlength指令是$ observe“minlength”属性,而不是“ngMinlength”属性。我认为问题在于Angular的输入指令是基于内插值设置minlength属性...所以当ngMinlength属性的值不随其值的变化而变化时,minlength属性就是可观察的原因。在您的指令中,属性observeMinLength不会更改,但传入的scope属性的值会更改。

如果您查看角度源代码:https://github.com/angular/angular.js/blob/13b7bf0bb5262400a06de6419312fe3010f79cb2/src/ng/directive/attrs.js#L379,您可以看到angular正在观察范围变量并为ALIASED_ATTR集合中的所有属性设置属性变量。该集合定义为

var ALIASED_ATTR = {
  'ngMinlength': 'minlength',
  'ngMaxlength': 'maxlength',
  'ngMin': 'min',
  'ngMax': 'max',
  'ngPattern': 'pattern'
};
https://github.com/angular/angular.js/blob/2e0e77ee80236a841085a599c800bd2c9695475e/src/jqLite.js#L575

中的

简而言之,Angular对其自己的基于属性的验证指令进行了特殊处理。因此,您需要观察范围属性,而不是观察属性。