Deny only one validator

I just read the awesome angular form validation page and I probably missed something, but how can I apply the ng-model-options debounce property on a specific validator.

Let me explain the problem. I have a form that checks the public key, and for this I have a directive called key-check, which contains several validators. Some of them are local and synchronous, like a key format, and there is another asynchronous check if the key is available on the server (asynchronously).

I don’t want my server to be flooded and the angular application to slow down, so I use what cool kids call debouncing and my input looks something like this:

 <input type="text" ... ng-model="key" key-check ng-model-options="{ debounce: 700 }" ng-minlength="5" ng-maxlength="50"/> 

And the directive is like:

 ctrl.$validators.keyFormatCheck = function(modelValue) { // return boolean } ctrl.$asyncValidators.KeyAvailabilityCheck = function(modelValue) { // return promise } 

It works like a charm, but all checks are performed with a delay of 700 ms, and I wonder if it is possible to execute keyFormatCheck without debouncing and KeyAvailabilityCheck with it. I can probably use the old good way with $ timeout, but I prefer to do it angular.

Any ideas?

+6
source share
1 answer

ngModelController debounce applies to the entire pipeline of parsers, validators, and change listeners (e.g. ng-change ).

Today there is no way (Angular v1.4) with ngModelOptions to allocate debounce delay for a specific validator.

But functionality is easily achieved by passing a delay parameter to its own asynchronous validator directive:

 <input ng-model="val" foo-validator="{delay: 500}"> 

You do the actual delay using $timeout ; there is no reason to avoid using $timeout on the grounds that it is somehow less than the "Angular way"; this is not true.

The only trick is to make sure you cancel the previous pending verification request before executing a new one.

 var pendingValidation; ngModel.$asyncValidators.foo = function(modelValue, viewValue){ if (pendingValidation) $timeout.cancel(pendingValidation); pendingValidation = $timeout(function(){ pendingValidation = null; // returns promise or value return doAsyncValidation(); }, delay); return pendingValidation; }; 

delay can be obtained from the parameter using the foo-validator either with binding to the selected area ( scope: {config: "=fooValidator"} ), or by directly using the $eval expression of the attribute expression in the right area:

 var config = $scope.$eval(attrs.fooValidator); var delay = config.delay; 
+5
source

All Articles