0

フォームには多くの検証を行うフィールドがあります。Angularで1回のhttp呼び出しに基づいて複数の検証を行う方法

最初は、それぞれ独自のエラーメッセージを持つ複数のディレクティブに構造化しました。

しかし、検証ではバックエンドの非同期呼び出しが使用されるため、突然1つのフィールドで同じデータサービスに対して5回のhttp呼び出しを行っていました。私はこれをより効率的に書く方法を理解しようとしています。

1つの$asyncのDataServiceを呼び出すバリデータ、および.then後の最初の非同期関数の内部に複数の定期的な$validatorsを持つことが可能である場合、私は思っていました。私はこれを実験しましたが、ネストされた$validatorsにはまったく届かないようです。

また、サービスで一度呼び出すことを試みましたが、フィールドのmodelValueが変更されたときに更新する方法を知りません。その結果、それぞれの検証ディレクティブに情報が渡されます。これをサービスの非同期検証として実行し、ディレクティブが検索する範囲に応答を添付できますか?

TLDR;

返されたデータに基づいて1つのhttp呼び出しを行い、複数の検証チェックを実行し、それぞれ独自のエラーが発生することはありますか?例

FOR

私はすべてがこのようになり、約4ディレクティブがあります。それぞれが異なるエラーメッセージを返すために、データの異なる分析を持って

angular.module('validationForField').directive('po', ['$q', '$sce', '$timeout', 'myService', function ($q, $sce, $timeout, myService) { 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function (scope, elem, attrs, ctrl, ngModel) { 
      ctrl.$asyncValidators.validateField = function (modelValue) { 
       var def = $q.defer(); 
       myService.httpcall(modelValue) 
        .then(function (response, modelValue) { 
         if (response.data.status === "Error") { 
          return def.reject(); 
         } 
        def.resolve(); 

        }).catch(function(){ 
        def.reject(); 
       }); 
       return def.promise; 
      } 
     } 
    } 
}]); 

を。それぞれがmyService.httpcallを呼び出して、すべてが同じデータを取得しているため、冗長になります。私は

angular.module('validationForField').directive('po', ['$q', '$sce', '$timeout', 'myService', function ($q, $sce, $timeout, myService) { 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function (scope, elem, attrs, ctrl, ngModel) { 
      ctrl.$asyncValidators.validateField = function (modelValue) { 
       var def = $q.defer(); 
       myService.httpcall(modelValue) 
        .then(function (response, modelValue) { 
         if (response.data.status === "Error") { 
          return def.reject(); 
         } 
         ctrl.$validators.checkStatus = function (response) { 
          if (response.data.data.status === "10"){ 
          return false 
         } 
         ctrl.$validators.checkPermissions = function (response) { 
          return response.data.data.permission){ 

         } 

        def.resolve(); 

        }).catch(function(){ 
        def.reject(); 
       }); 
       return def.promise; 
      } 
     } 
    } 
}]); 

このHTTP呼び出しが成功したかどうかについての主な非同期バリがある道、そしてそれが

+0

あなたの質問に関連したフィドルまたはビンを作成するか、少なくともコードの一部を共有できますか? – mamsoudi

+0

@ mamos98はそれを助けますか? – jenryb

答えて

1

を返したときにそのデータを使用して内部の$バリデータを実行しようとしてい

// true would mean valid, string would mean invalid with the given error: 
{ 
    businessRuleOne: true, 
    businessRuleTwo: "The format is incorrect", 
    ... 
} 

私は信じている:私は、バックエンドサービスは、例えば、値(検証されるフィールドの値)を受け入れ、すべての検証のための単一の応答を返すと仮定しますソリューションは、約束をキャッシュするサービスでHTTPコールを実行しています。非同期バリデーターはサービスを呼び出し、同じ約束を検索して返します。インラインの説明を含むサンプルコード:

// the service: 
app.service('myService', function($http, $q) { 
    // cache the requests, keyed by the model value 
    var requestMap = {}; 

    this.httpcall = function(modelValue) { 
     // if cached, return that (and do not make extra call) 
     if(requestMap[modelValue]) { 
      return requestMap[modelValue]; 
     } 
     // if not cahced, make the call... 
     var promise = $http.get('....'); 
     // ...cache it... 
     requestMap[modelValue] = promise; 
     // ...and remember to remove it from cache when done 
     promise.finally(function() { 
      delete requestMap[modelValue]; 
     }); 
     return promise; 
    }; 
}); 

これで、非同期バリデータは投稿と同じように実装できます。 myService.httpcall(modelValue)を呼び出すと、最初の呼び出しに対してのみリモートサービスが呼び出され、残りの部分はキャッシュされた約束が再利用されます。


さらに2つのポイント:(1)このテクニックはメモ作成と呼ばれます。これは多くのライブラリによって実装されています。 lodashを使用すると、myservice.httpcall()をきれいに保つことができます。 (2)非同期バリデータから余分な約束をする必要はありません。:

angular.module('validationForField').directive('po', ['$q', '$sce', '$timeout', 'myService', function ($q, $sce, $timeout, myService) { 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function (scope, elem, attrs, ctrl, ngModel) { 
      ctrl.$asyncValidators.validateField = function (modelValue) { 
       return myService.httpcall(modelValue) 
        .then(function (response) { 
         if (response.data.status === "Error") { 
          return $q.reject(); 
         } 
         return response; 
        }); 
      } 
     } 
    } 
}]); 
+0

私はこのソリューションが本当に好きです。私は同じような実装を試みました。問題は、各ディレクティブが同時にサービスを呼び出していたため、すべてがif(requestMap [modelValue])部分に行き、すべてが偽になり、その後すべてが$ http.get。 if文の実装が正しくない可能性があります。私はあなたのバージョンを使用しようとし、それが動作しない場合は新しい質問を開きます。 – jenryb

+0

JavaScriptはシングルスレッドであるため、すべての呼び出しが "if"行に同時に到達するように努力する必要があります。 –

関連する問題