Персонализирана директива notPattern като ngPattern, но проверка дали RegExp не съвпада

Опитвам се да напиша персонализирана директива AngularJS, подобна на ngPattern, с изключение на това, че тази директива няма да успее при валидиране, ако RegExp не съвпада.

След източника на 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“ в текстовото поле ще покаже „Невалидно за „образец“!“. Очаквах да видя "Невалидно за 'notpattern'!" когато се въведе "abc", но това се появява само когато въведа "testRegExp", което показва, че стойността на атрибута не се оценява.

какво правя грешно

Знам, че notPattern може да се постигне с ngPattern чрез нещо като:

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

.. но бих искал да знам защо персонализираната директива не оценява израза.


person Daniel Trebbien    schedule 12.06.2015    source източник


Отговори (1)


Оказва се, че ngPattern е специален случай в рамките на Angular на „atr с псевдоним за въвеждане“, което означава, че часовникът е настроен да оценява израза чрез директива с по-висок приоритет. Функцията за гледане на слушател просто задава атрибута на оценения резултат всеки път:
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/

person Daniel Trebbien    schedule 17.06.2015