Marc Rasmussen Marc Rasmussen - 1 month ago 11
Javascript Question

angular setting form invalid through directive

I am creating a remote validation directive that allows me to check with my server if the field is validated.

So far i have this:

angular.module('Form').directive('remoteFieldValidation', function (Query) {
return {
restrict: 'A',
scope: {
fieldValue: '=ngModel'
},
link: function (scope, element, attr) {
element.parent().addClass('has-feedback');
element.focusout(function (value) {
var value = scope.fieldValue;
var checker = attr.remoteFieldValidation;
if (value && checker) {
element.parent().append('<span class="form-control-feedback fa fa-spinner fa-spin" style="line-height: 35px"></span>');
Query.api2({
method: 'GET',
route: 'validateField',
params: {
value: value,
checker: checker
}
}).then(function (result) {
})
}
else {
console.log('Missing checker or value');
}
})
}
}
});


For clearance Query is my own API service basically it controls
$http requests
.

Now when i add this attribute directive to an input field i would like to make sure that once it starts validating it sets the form as invalid.

However i'm not quite sure how to reach the form from this directive.

Does anyone know how i might do this to prevent that users submit the form before my remote validation is checked?

Answer

You could do this in a static way just by making your submit action wait the server to validate your field. However, a better approach would be adding an $asyncValidator on your ngModel. It's a feature brought on AngularJs 1.3 release.

By using this solution you'd be able to catch the validation errors using angular form atributes:

<div ng-show="form.myField.$error.myRemoteValidator">The value is not valid!</div>

Or using ngMessages like so:

<div ng-messages="form.myField.$error">
    <div ng-message="myRemoteValidator">The value is not valid!</div>
</div>

Your directives would look like:

angular.module('Form')
     .directive('remoteFieldValidation', function(Query, $q) {
       return {
         restrict: 'A',
         require: 'ngModel',
         link: function(scope, element, attr, ngModelCtrl) {
           ngModelCtrl.$asyncValidators
             .myRemoteValidator = function(modelValue, viewValue) {
               var value = modelValue || viewValue;
               var checker = attr.remoteFieldValidation;

               return Query.api2({
                 method: 'GET',
                 route: 'validateField',
                 params: {
                   value: value,
                   checker: checker
                 }
               }).then(function(result) {
                 if (result.isValid) {
                   // it says to validator that it's valid
                   return true;
                 } else {
                   // it says to validator that it's not valid
                   // and also send the error message
                   return $q.reject('Invalid field');
                 }
               }, $q.reject); // invalidate in case of any errors on your api or request 
             };
         }
       }
     });

UPDATE

Example:

<form name="form">
    ...
    <input type="text" ng-model="myField" remote-field-validation>
    <div ng-messages="form.myField.$error">
        <div ng-message="myRemoteValidator">The value is not valid!</div>
    </div>
    ...
    <button ng-disabled="form.$invalid">Save</button>
</form>
Comments