0

入力に対してクライアント側とサーバー側の検証を確立するために使用されるディレクティブを作成しています。バリデーター名の配列を受け入れ (例: aa-validate="required,unique")、それらをループし、すべての可能なバリデーターに対してクライアント側の検証ディレクティブを追加し (例:requiredを追加する必要がngRequiredあります)、残りについてはサーバー側の検証 API に送信します。

その最後の部分はうまく機能します。ngModel属性を監視し、100 ミリ秒のタイムアウトでサーバーに投稿しています。ただし、ディレクティブのリンク関数内からクライアント側の検証ディレクティブを設定しても、それらはコンパイルおよびリンクされません。つまり、彼らは何もしません。これが私のコードです:

angular.module('form', [])
    .directive('aaValidate', ['$http', function($http) {
        return {
            priority: 1,
            restrict: 'A',
            require: 'ngModel',
            link: function(scope, element, attrs, ctrl) {
                var validate = attrs.aaValidate,
                    validators = validate.split(',');

                // This is the problem!
                //
                // Populate possible client-side validators
                for (var i = 0, len = validators.length; i < len; i++) {
                    var validator = validators[i];
                    switch (validator) {
                        case 'required':
                            attrs.$set('ngRequired', 'true'); break;
                        // ... and so on for ngPattern, etc.
                        default: break;
                    }
                }

                scope.$watch(attrs.ngModel, function(value) {
                    // This part works!
                    //
                    // Clear existing timeout, reset it with an
                    // $http.post to my validation API, the result is
                    // passed into ctrl.$setValidity
                });
            }
        }
    }]);

$compileを挿入し、リンク関数の最後で要素を再コンパイルしようとしました。おそらくいくつかの属性を削除できなかったため、無限再帰になってしまいましたが、このようにできたとしても、かなり醜い感じがします。正しいアプローチは何ですか?

どんな助けでも大歓迎です。前もって感謝します。


編集: jsFiddle: http://jsfiddle.net/3nUdj/4/

4

1 に答える 1

1

私の最初の答えは間違っていました。このサービスを使用する方法はないと思います$compile。無限再帰を取得せずにそれを行う方法は次のとおりです。基本的に、ディレクティブを 2 つのディレクティブに分割します。1 つは検証ディレクティブを追加し、それ自体を削除して再コンパイルします。もう一方は他のことを行います:

angular.module('form', [])
.directive('aaValidate', ['$http', '$compile', function ($http, $compile) {
  return {
    link: function (scope, element, attrs) {
      var validate = attrs.aaValidate,
          validators = validate.split(',');

      // Populate possible front-end validators
      for (var i = 0, len = validators.length; i < len; i++) {
        var validator = validators[i];
        switch (validator) {
          case 'required':
            attrs.$set('ngRequired', 'true');
            break;
          default:
            break;
        }
      }
      attrs.$set('aaOther', '');
      element.removeAttr('aa-validate');
      $compile(element)(scope);
    }
  }
}])

.directive('aaOther', function () {
    return {
      require: 'ngModel',
      link: function (scope, element, attrs, ctrl) {
        scope.$watch(attrs.ngModel, function (value) {
          // Server-side validation
        });
      }
    }
});

これを ng-repeat で機能させるには、リンクされた要素を再コンパイルする必要があります。フィドルを更新しました: http://jsfiddle.net/3nUdj/7/

于 2013-05-24T19:06:48.797 に答える