4

My ASP.NET MVC4 application has a remote validation rule defined in model and implemented in a controller method. My form is dynamically added to the page. So, I used the following code to trigger the validation.

$(tabId).on("submit", formId, function (event) {
       event.preventDefault();

       var form = $(this);

       form.removeData("validator"); 
       $.validator.unobtrusive.parse(form);

       if (form.valid())
       {
           // form submission 

           // THIS part executes even though the remote validation returns false
       }

       return false;
 });

It starts remote validation and doesn't wait for the completion and then submits the form. If any other field is non-valid (say, name is a required field), then it stops the submission. However, it doesn't wait for the remote validation.

I found some work around on SO such as link1 and link2. However, these work only if I have jQuery validation rules defined in my page. However, I'm using MVC4 model validation rules. Thus I am not interested to redefine the rules in my view page again.

Any idea to solve?

Community
  • 1
  • 1
N Rocking
  • 2,947
  • 2
  • 21
  • 24

4 Answers4

5

You can use the pendingRequest variable on the validator to see if there are any still pending when the form tries to submit

$(tabId).on("submit", formId, function (event) {
       event.preventDefault();
       var form = $('#formid');
       form.removeData("validator"); 
       $.validator.unobtrusive.parse(form);

       if (form.valid() && form.data('validator').pendingRequest == 0)
       {
           // form submission 
       } 
       return false;         
});  

And if you want to show messages to the user while the field is validating, you can use the startrequest and stopRequest functions:

$(function(){
    var validator = $('#formid').data('validator');

    var oldStartRequest = validator.startRequest;
    validator.startRequest = function (element) {     
        console.log(element.name + ' has begun validating')
        oldStartRequest.apply(this, arguments);
    };

    var oldStopRequest = validator.stopRequest;
    validator.stopRequest = function (element, valid) {
        console.log(element.name + ' has finished validating');
        console.log(element.name + ' is valid: ' + valid)
        oldStopRequest.apply(this, arguments);
    };
});
brocknz
  • 226
  • 2
  • 7
0

You should call the $.validator.unobtrusive.parse(form) as soon as the form gets added to the page. Calling it in a submit event is not correct and is most likely your problem. One of the things Validator and Unobtrusive do is capture those events for you, and due to the way Unobtrusive works, if you want to do specific things on successful submit, you have to sneakily attach yourself to the submitHandler like so:

$('#nameForm').data('validator').settings.submitHandler = function(form){
   alert('successful submit'); 

   //do AJAX submit here

   return false; //otherwise page will get reloaded
};

I've made a working example for you, but note that due to the way jsfiddle works, it's somewhat hard to do an AJAX call, so I had to add a hidden field called html which if you change the value of between true and false you can see the different behaviours.

http://jsfiddle.net/ryleyb/ZeZAu/1/

Ryley
  • 21,046
  • 2
  • 67
  • 81
  • [Helpful discussion](http://stackoverflow.com/questions/4747017/how-to-add-a-submithandler-function-when-using-jquery-unobtrusive-validation) of how to deal with valid/invalid forms that doesn't break the way Validate/Unobtrusive works – Ryley Nov 21 '13 at 18:53
0

You could attach to the global ajax events and make sure nothing is waiting for a reply when you submit the form. Untested e.g.

var isInAjaxCall = false;
var queuedFuncs = [];
$(function() {
    $(document).bind("ajaxStart", function () {
        isInAjaxCall = true;
     }).bind("ajaxStop", function () {
        isInAjaxCall = false;
        while(queuedFuncs.length > 0){
           queuedFuncs.shift();
        }
    });
});

function SubmitForm() {
    if (isInAjaxCall) {
        queuedFuncs.push('SubmitForm');
        return false;
    }

    var form = $('#form');
    form.removeData("validator");
    $.validator.unobtrusive.parse(form);

    if (form.valid()) {
        // form submission 
    }
    return false;
}
brocknz
  • 226
  • 2
  • 7
0

My post here provides the solution, but there must be a better way:

ASP.NET-MVC jQuery unobtrusive remote validation returns false positives

Community
  • 1
  • 1
GP24
  • 867
  • 2
  • 13
  • 28