0

我在一個有很多驗證的表單上有一個字段。如何在Angular中基於一個http調用進行多個驗證

起初,我把它組織成了多個指令,每個指令都有自己的錯誤信息。

但是,驗證使用後端異步調用,所以突然之間我爲同一個數據服務器創建了5個http調用。我試圖弄清楚如何更有效地寫這個。

我想知道是否有可能有一個$async驗證程序調用dataservice,而多個常規$validators內部的第一個異步函數在.then之後。我對此進行了實驗,但它似乎完全沒有達到嵌套$validators

我也嘗試在服務中調用一次,但是我不知道如何在字段上的modelValue發生更改時更新它,並因此將信息傳遞給相應的驗證指令。我可以將它作爲服務中的異步驗證並將響應附加到指令查找的範圍嗎?

TLDR;

如何進行一個http調用並基於返回的數據執行多個驗證檢查,每個驗證檢查都有自己的錯誤?

FOR EXAMPLE

我有大約四個指令,所有看起來像這樣:

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)將僅爲第一次調用調用遠程服務,其餘部分將重新使用緩存的承諾。


還有兩點:(1)這種技術被稱爲memoization。它由許多圖書館實施,例如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])部分,全部都變爲false,然後全部進入$ http.get。也許我的if語句的實現是不正確的。如果這不起作用,我會嘗試使用您的版本並開放一個新問題。 – jenryb

+0

Javascript是單線程的,您必須儘量讓所有呼叫同時到達「if」行。 –

相關問題