1

我正在尝试编写一个类似于 ngPattern 的自定义 AngularJS 指令,但如果 R​​egExp匹配,该指令将无法验证。

根据ngPattern 指令的来源,我想出了:

  .directive("notPattern", function () {
    return {
      restrict: "A",
      require: "?ngModel",
      link: function (scope, elem, attr, ctrl) {
        if (!ctrl) return;

        var regExp, notPatternExp = attr.notPattern;
        attr.$observe("notPattern", function (regex) {
          if (angular.isString(regex) && regex.length > 0) {
            regex = new RegExp("^" + regex + "$");
          }

          if (regex && !regex.test) {
            var elemClone = angular.element(elem).clone();
            var elemHtml = angular.element("<div>").append(elemClone).html();
            throw new Error("Expected " + notPatternExp + " to be a RegExp but was " + regex + ". Element: " + elemHtml);
          }

          regExp = regex || undefined;
          ctrl.$validate();
        });

        ctrl.$validators.notpattern = function (value) {
          return ctrl.$isEmpty(value) || angular.isUndefined(regExp) || !regExp.test(value);
        };
      }
    };
  })

这在我在属性中指定正则表达式源时有效,但我想允许RegExp直接使用对象,例如 ngPattern。

问题是表达式没有被评估。

这是一个示例 JSFiddle:http:
//jsfiddle.net/8Lk3pqep/1/

在此示例中,在文本字段中输入“abc”以外的任何内容将显示“Invalid per 'pattern'!”。我希望看到“每个 'notpattern' 无效!” 输入“abc”时,但仅当我输入“testRegExp”时才会出现,因此表明未评估属性值。

我究竟做错了什么?

我知道 notPattern 可以通过以下方式使用 ngPattern 来完成:

$scope.testRegExp = {
  test: function (value) {
    return !/^abc$/.test(value);
  }
};

..但我想知道为什么自定义指令不评估表达式。

4

1 回答 1

0

事实证明,ngPattern 是 Angular 中“别名输入属性”的一种特殊情况,这意味着设置了一个监视来通过更高优先级的指令评估表达式。watch 监听器函数每次都简单地将属性设置为评估结果:
https ://github.com/angular/angular.js/blob/bfcf9946e16d21b55dde50d4d21c71c898b10215/src/ng/directive/attrs.js#L377

要修复 notPattern 指令,而不是观察 notPattern 属性,设置 notPattern 表达式的监视以反映 ngPattern 属性的内置设置:

  .directive("notPattern", function () {
    return {
      restrict: "A",
      require: "?ngModel",
      link: function (scope, elem, attr, ctrl) {
        if (!ctrl) return;

        var regExp, notPatternExp = attr.notPattern;
        scope.$watch(notPatternExp, function (regex) {
          if (angular.isString(regex) && regex.length > 0) {
            regex = new RegExp("^" + regex + "$");
          }

          if (regex && !regex.test) {
            var elemClone = angular.element(elem).clone();
            var elemHtml = angular.element("<div>").append(elemClone).html();
            throw new Error("Expected " + notPatternExp + " to be a RegExp but was " + regex + ". Element: " + elemHtml);
          }

          regExp = regex || undefined;
          ctrl.$validate();
        });

        ctrl.$validators.notpattern = function (value) {
          return ctrl.$isEmpty(value) || angular.isUndefined(regExp) || !regExp.test(value);
        };
      }
    };
  })

这是一个更新的 JSFiddle:http:
//jsfiddle.net/8Lk3pqep/2/

于 2015-06-17T22:42:47.083 回答