Mouss Mouss - 23 days ago 12
AngularJS Question

Asynchronous validation on blur Angular JS

I am using Angular JS 1.5.6 and I would like to perform asynchronous input validation that would occure only on blur. I specify that this directive is used with other directives so I can neither use modelOption: {debounce: 500} nor use modelOption: {updateOn: 'blur'}.

I have tryied the code bellow but curiously on the first blur, no async validation is done, and when I come back to the input the async validation is performed for each typed character, which is exactly what I would like to avoid.

function blurFocusDirective($http, $q) {
return {
require: 'ngModel',
link: function(scope, elm, attrs, modelCtrl) {
elm.on('blur', function() {
console.log('capture blur event');

modelCtrl.$asyncValidators.myValidator = function(modelValue, viewValue) {
return $http.get('/username-check/' + modelValue).then(
function(response) {
if (!response.data.validUsername) {
return $q.reject(response.data.errorMessage);
}
return true;
}
);
};
});
}
};


}

I have plunkered the issue, press F12 to see what is happening in the console.

I precise that the WS '/username-check/' is a fake, it is not linked to the issue I want to solve. My issue is that the async HTTP request is done at each typed character, whereas I would like it to be done only on blur

Answer

You have a issue with your code. Every time, when onblur event occurs, when creating new async validator! It validator working every time, when ngModel is changed.

Try this. You can set validation manually.

elm.on('blur', function() {
      console.log('capture blur event');

      $http.get('/username-check/' + modelCtrl.$modelValue).then(
        function(response) {
          if (response.data.validUsername)
            modelCtrl.$setValidity("myValidation",true);
          else
            modelCtrl.$setValidity("myValidation",false);
        }
      ).catch(function() {
        modelCtrl.$setValidity("myValidation",false);
      });

    });

Example on plunker