1

RegExp が一致しない場合、このディレクティブは検証に失敗することを除いて、ngPattern に似たカスタム AngularJS ディレクティブを作成しようとしています。

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);
        };
      }
    };
  })

これは、属性内で正規表現ソースを指定すると機能しますが、RegExpngPattern のように、オブジェクトを直接使用できるようにしたいと考えています。

問題は、式が評価されていないことです。

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 内の「エイリアス入力属性」の特殊なケースであることが判明しました。これは、より優先度の高いディレクティブを介して式を評価するようにウォッチが設定されていることを意味します。ウォッチ リスナー関数は、毎回評価された結果に属性を設定するだけです

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 に答える