AngularJS: custom validator trying to check immediately

I have a form where some inputs are connected to a custom validator using a directive. The input must be checked for blur, and does so through an asynchronous call to the REST API.

HTML:

<input type="text" validate-this ng-model="thisField" ng-model-options="{'updateOn': 'blur'}" ng-pattern="some pattern" /> 

Directive (abbreviated for brevity):

 return { access: 'A', require: 'ngModel', scope: false, link: function (scope, elem, attrs, ngModel) { ngModel.$asyncValidators.validateThis = function (modelVal, viewVal) { if (!modelVal && !viewVal) return $q.defer().promise; // returns a promise from the api service return api.doSomeValidation(); }; } }; 

The above code works fine, but pay attention to the hacker line directly below the signature of the verification function:

if (!modelVal && !viewVal) return $q.defer().promise;

Without this line, Angular tries to check the field immediately when the application loads, and not just for blurring. This is a problem because the actual verification code does some string parsing, and since both modelVal and viewVal are undefined , JavaScript throws an error.

I tried disabling functionality that loads data into fields when the application loads, and the error still occurs. However, the template specified in ng-pattern does , respects my wishes and checks only for blurring the field - it does NOT try to check for page loading. Is there a way to tell Angular to only check for blur, or make it stop trying to check as soon as the page loads? Or am I using $asyncValidators ?

+2
javascript angularjs
Oct 27 '14 at 2:49
source share
1 answer

Angular does $ validate during the signal of each attr. $ is observed for input directives such as ngPattern. You can see this in your patternDirective function.

I am trying to find a way around this, since I use many input checks (pattern, maximum length, required, etc.), and my $ asyncValidators are run 7 times at boot time. This caused the web server to execute for each trigger.

Solutions:

  • cache web method response
  • attach your handler after loading the page (or enter some flag)
  • bake the ngPattern test in the async handler. I will probably go with this.

     ngModel.$asyncValidators.validateThis = function (modelVal, viewVal) { var deferred = $q.defer(); if (!modelVal && !viewVal) deferred.resolve(); else if (!myPattern.test(modelVal)) deferred.reject(); else api.doSomeValidation(value).then(function (result) { deferred.resolve(); }, function (result) { deferred.reject(); }) return deferred.promise; }; 

Hope this helps as I am in the same boat looking for a solution.

+2
Dec 10 '14 at 17:57
source share



All Articles