Client-side jQuery Ajax Support

Mar 4, 2009 at 6:58 AM
Hi Steve,

Is the clientside portion of xVal supported with jQuery $.ajax() calls? If so, could I see an example?
As currently firing the submit button does not raise client-side validation.  I believe server-side validation is ok and I can handle this in the error block.

My JS code that I would like to encorporate xVal with client validation is as below.

var formData = $("#myForm").serializeArray();
                $.ajax({
                    type: "POST",
                    url: "test/submit/url",
                    data: formData,
                    dataType: "html",
                    success: function(result) {
                        alert(result);
                    },
                    error: function(req, status, error) {
                        alert(error);
                    }
                });

Any chances or no available support?
Mar 4, 2009 at 11:41 AM
Goneale

You want to fire the Ajax post on successful validation of the form. Using Jquery Validate checkout the "submitHandler".
http://docs.jquery.com/Plugins/Validation/validate#toptions

This will ensure that the client side rules are ran before the form is submitted.
Now say for exaple the client side rules are valdiated and the data posts to the server and then your ValidationRunner returns either invalid data or invalid business rules you will need to serialize that data to a JSON format and deal with it client side.

Does this help?

Mark

Mar 4, 2009 at 11:12 PM
Thanks Mark, this is exactly what I was thinking - I did try the validate() method but then either validation did not appear to fire, as I didn't get any highlighted fields and even when I typed information into all fields it still didn't perform the ajax call.

I will set up the test case again and show you my code.

Yep I am happy to serialise the data to JSON for errors.  Probably would have to implement the server-side field error labels manually, but could do that via JS and JSON if I really am keen.
Mar 5, 2009 at 12:15 AM
Hi Mark,

Just at the last minute I found out what I was doing wrong.  My button had been calling an onclick() all this time and not using onsubmit() at the form level, that's why submitHandler() was never firing and all validation messages were being supressed!
Thanks for your help, I should be well on my way now.
Mar 5, 2009 at 1:22 AM
Edited Mar 5, 2009 at 1:22 AM
OK, I shouldn't speak too soon.  It seems that now the validation messages are displaying, but my handlers are still not firing.

To demonstrate I have used the Bookings Demo.  See attached.
Mar 5, 2009 at 9:33 AM
Edited Mar 5, 2009 at 9:35 AM
Your problem is this:

When you output the xVal javascript it will make a call to $('myForm').validate passing in the default xVal options defined in the xVal.jquery.validate.js file "_ensureFormIsMarkedForValidation" is the name of the function. I have in the past just edited this file to inject my application wide Jquery Validate options if I am straying from the defaults.

You are then in your run() function trying to overwite these settings with new ones, however the jQuery.Validate library does a check to see if .validate() has already been caleed for the form (which it has earlier by the xVal javascript) and returns the xVal settings and does not accept your ones. Fortunately jQuery.Valite library uses the .data part of jquery to store its settings and a simple call to removeData is all you need to make your test project work.

function run() {
$("#myForm").removeData("validator"); //Here is where we remove the xVal Validate settings.
$("#myForm").validate({
errorClass: "field-validation-error",
errorElement: "span",
highlight: function(element) { $(element).addClass("input-validation-error"); },
unhighlight: function(element) { $(element).removeClass("input-validation-error"); },
submitHandler: function() { alert("Submitted!") },
invalidHandler: function(form, validator) { alert(validator.numberOfInvalids()) }
});
}

Let me know how you get on.

Thanks, Mark
Mar 5, 2009 at 11:12 PM
Hi Mark, I basically understand.  However I would want to keep the xVal settings wouldn't I and simply just validate the form? I don't know if I'm making sense.

Either way when I perform the removeData() statement and hit submit, I do get further, it displays the number of errors, but it does this twice.  Then if you press submit, it does it this like 4 times, and then continually exponentating each submit click.  Now implementing this in my own app, when validation succeeds it posts in the background the same amount of times, 2, and then 4.  Not what we want :(

Not sure if you have looked at the app to replicate this behaviour?
Mar 6, 2009 at 12:29 AM
Thats because you are not setting the jQuery validate options once and once only. Every time you are hitting the submit button it's running your "run()" function and somewhere in the internals of jquery validate it's enumerating over the same valdiate options again and again.

You have a couple of options:

1.) Edit the xVal.Validate.js file and modify the "_ensureFormIsMarkedForValidation" function to include your custom ajax form post stuff. This will however mean you will have the same behaviour for each form.
2.) Remove the call to  "_ensureFormIsMarkedForValidation" from the xVal.Validate.js file and include the call to "$("#myForm").validate()" using normal jquery:

$(document),ready(function(){
//Your validate setup code goes here.
});

Which will mean you will need to include this code on every page you want to use xVal on.

3.) Dig a little deeper than I manged to do into the jquery.validate.js code and see if after xVal has setup the jquery,validate() call you can modify any of the options. I am assuming you might be able to do something like:

$(document).ready(function(){
$.data($('#myForm'),'validate').options.submitHandler = function() { alert("Submitted!")}; 
});

In order to inject your custom submitHandler code after jquery.validate has been called.
I will see if I can get your sample to work using the #3 method which seems like the right thing to do in this instance but it won't be until tomorrow.

Thanks, Mark

Mar 6, 2009 at 2:51 AM
Ok, thanks for all your help Mark.  As you can see I'm attempting to implement the most frictionless option as possible as that's ideally what we want for myself and everyone who wishes to also do this for xVal to be as powerful as it can be   (But I understand this is more a jquery validate setup issue).  I will read your email closer when I get more time and attempt to also look at option 3 as you state.

Cheers.
Mar 6, 2009 at 1:09 PM
The solution is to include this in the jquery document.ready.

var valdiator = $('#myForm').validate();
validator.settings.submitHandler = function() {alert('new submitHandlerInvoked')};

You are right in that frictionless is the best. I will add this approach to the documentation stuff I am putting together.

I knew it could be solved it just not something that came up right away on google.

Hope you can get on with using more of xVal now. I am using it on two projects at the moment and finding it reduces my validation code substantially.

Mark
Coordinator
Mar 25, 2009 at 3:58 PM
Edited Mar 25, 2009 at 3:59 PM
Finally got chance to look at this. Sorry it took so long.

As Mark says above, you can add jQuery.Validator submitHandler and invalidHandler without having to edit xVal.jquery.validate.js. For example, add the following *after* your call to Html.ClientSideValidation():

<script type="text/javascript">
    $(function() {
        $("#myform").validate().settings.submitHandler = function(form) {
            $.ajax({
                type: "POST",
                url: "/Home/PlaceBookingAjax",
                data: $("form").serializeArray(),
                dataType: "json",
                success: function(resultObject) {
                    alert("Success. Action method returned: " + resultObject);
                }
            });
        }

        $("#myform").bind("invalid-form.validate", function(form, validator) {
            alert(validator.numberOfInvalids() + " things are wrong here.");
        });
    });                
</script>

Note that the tricky bit is if the server-side validation reports an error that the client-side validation didn't detect. In that case, you need some way of communicating those errors back to the client and displaying them.