4

I have a form that has a username field and other fields, this field has an async validator that checks whether that username is available when you try to submit the form (there are other fields on the form using async validation). I use this directive to validate and submit the form (only if it's valid):

<form validation-submit="submit()"></form>
app.directive('validationSubmit', ['$parse', function($parse) {
    return {
        restrict: 'A',
        require: '?form',
        compile: function($element, attr) {
            var submitFn = $parse(attr.validationSubmit);

            return function link(scope, element, attrs, FormController) {
                var submit = function(event) {
                    scope.$apply(function() {
                        if (! FormController.$valid) {
                            return;
                        }

                        submitFn(scope, {$event: event}));
                    });
                };

                element.bind('submit', submit);

                scope.$on('$destroy', function() {
                    return element.off('submit', submit);
                });
            }
        }
    };
}]);

The problem is this directive is not waiting for the pending async validations to finish. How can I change this directive to only submit after all async validations finished and passed?

5
  • 1
    You'll need to validate server-side on submit anyway (never trust client data and all that), so why not just submit immediately? Commented Dec 8, 2014 at 8:42
  • totally agree with Alan... and if you really want to do the async validation do it on that particular username field, rather than on submit... Commented Dec 8, 2014 at 8:45
  • @harish Ok let's say I do the validation on that particular field - how can I prevent the submit until it finished validation on that field? Commented Dec 8, 2014 at 8:48
  • 1
    if you do validation on that field, your form would be invalid, and you can just use ng-submit as ng-submit='formname.$valid && doSubmit()' on the form element Commented Dec 8, 2014 at 8:53
  • angular doesn't push the view value to the model value until all validators pass, including async ones, so he can't just submit to the server and get server-side validation errors. I need to know the answer to this question too. Commented Feb 26, 2015 at 16:17

1 Answer 1

1

Recently I've created a couple of directives that were checking whether email or phone number is available. I found solution that helps me. It's $asyncValidators .

app.directive('validationSubmit', ['$parse', function($parse) {
    return {
        restrict: 'A',
        require: '?form',
         link: function(scope, element, attrs, FormController) {
                /**
                *returns promise
                **/
                FormController.$asyncValidators.validEmail = function (modelValue) {
                    return $q(function (resolve, reject) { 
                    //Here you should make query to your server and find out wether username valid or not
                    //For example it could be:
                    $http('http://your_api_server/Available').then(function (response) {
                            if (response.data.Available) {
                                resolve();
                            } else {
                                reject();
                            }
                        }, function (err) {
                            reject(err.data);
                        });  
                        });
                };
            }

    };
}]);

You should add attribute name to the form:

<form validation-submit="submit()" name="myForm"></form>

And now you have opportunity to check system properties of form in your controller:

$scope.submit = function(){
    //Here will be your logic
    if($scope.myForm.$valid ||
       $scope.myForm.$invalid || 
       $scope.myForm.$pending ||
       $scope.myForm.$submitted){
          //do whatever you want
        }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.