Call MVC 3 Client Side Validation Manually for ajax posts
Asked Answered
S

8

61

I am creating an MVC 3 web application. I want to use Data Annotations on my entity class and then use unobtrusive client side validation before making a post back to the server. This works fine when making a regular post. I get validation and the validation summary if any of the fields are not valid. However, I want to post back the information via ajax and json. How can I 'manually' validate the form on the client side first then make my ajax post back to the server. Below is a summarized version of my code.

  public class Customer
    {
        [Required(ErrorMessage = "The customer's first name is required.")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "The customer's last name is required.")]
        public string LastName { get; set; }
    }



    <% using (Html.BeginForm()) { %>

    <%: Html.LabelFor(model => model.FirstName, "First Name")%>
    <%: Html.TextBoxFor(model => model.FirstName, new { @class = "TextBox", id = "Customer.FirstName" })%>
    <%: Html.ValidationMessageFor(model => model.FirstName, "*")%>

    <%: Html.LabelFor(model => model.LastName, "Last Name")%>
    <%: Html.TextBoxFor(model => model.LastName, new { @class = "TextBox", id = "Customer.LastName" })%>
    <%: Html.ValidationMessageFor(model => model.LastName, "*")%>

    <div id="CustomerEditSave" class="Button CustomerEditButtons" style="margin-right:40px;">
       <a href="#">Save</a>
    </div>

    <%: Html.ValidationSummary(true) %>

    <% } %>

I have tried this code but it only validates the first name and does not display the validation summary.

    $("#CustomerEditSave").click(function () {
        $(form).validate();
        //Ajax call here
    });
Socorrosocotra answered 26/2, 2011 at 15:39 Comment(0)
C
98

Try:

//using the form as the jQuery selector (recommended)
$('form').submit(function(evt) {
    evt.preventDefault();
    var $form = $(this);
    if($form.valid()) {
        //Ajax call here
    }
});

//using the click event on the submit button
$('#buttonId').click(function(evt) {
    evt.preventDefault();
    var $form = $('form');
    if($form.valid()) {
        //Ajax call here
    }
});

This should work with jQuery ajax and MSAjax calls. Could also try using http://nuget.org/packages/TakeCommand.js or https://github.com/webadvanced/takeCommand it will automatically handle this for you.

Cicatrix answered 27/2, 2011 at 5:25 Comment(4)
as I mentioned in the comment below - performing ajax calls in click can result in the submit call trumping the ajax call if you don't explicitly handle the cancellation of the submit action by returning false... which means the solution requires two functions be written instead of one...Cisco
@DrRob, you should never return false, you should capture the jQuery event as a param and call preventDefault(). If your click handler uses return false to prevent browser navigation, it opens the possibility that the interpreter will not reach the return statement and the browser will proceed to execute the anchor tag's default behavior. This is what was causing your problem, not because you were using click vs submit. The benefit to using event.preventDefault() is that you can add this as the first line in the handler, thereby guaranteeing that the anchor's default behavior will not fire.Cicatrix
evt.preventDefault(); love this use it all the time now instead of returning false.Socorrosocotra
@Paul-after searching a lot, finally i got the solution from you answer. :)Maun
C
24

I have been phaffing about with MVC client side validation for days:

Don't use .click use .submit:

$("#MyForm").on('submit',function () {

    if($("#MyForm").valid())
    {
        //Do ajax stuff
    }

    //Return false regardless of validation to stop form submitting
    //prior to ajax doing its thing
    return false;
});

I'm going add an update to this, consider cancelling the event rather than returning false (or do both):

$("#MyForm").on('submit',function (e) {

    if($("#MyForm").valid())
    {
        //Do ajax stuff
    }

    e.preventDefault();

    //Return false regardless of validation to stop form submitting
    //prior to ajax doing its thing
    return false;
});
Cisco answered 27/2, 2011 at 11:52 Comment(5)
Excellent solution. Thank you very much. I to was wasting time over this one the last couple of days.Socorrosocotra
And another note, be sure to have jquery.validate.min.js and jquery.validate.unobtrusive.min.js referenced on the page or your form will not have a .valid() method.Easting
@Easting +1 - Totally agree with you... I keep forgetting that ;-)Swaggering
-1. This answer makes a suggestion that is wrong. See my post below. It works because you wrapped the if statement ($("#MyForm).valid()) around the ajax call, not because you used .submit rather than .click. There is NO PROBLEM in using both!Morning
what about a call to preventDefault() ?Enunciation
W
10

At least in my case (MVC 5), it was also necessary to add the following code or else .valid() would always return true:

$(function () {
$(document).ajaxComplete(function(event, request, settings){
    //re-parse the DOM after Ajax to enable client validation for any new form fields that have it enabled
    $.validator.unobtrusive.parse(document);
});

});

See http://johnculviner.com/the-unobtrusive-libraries-client-validation-on-ajax-in-asp-net-mvc-3/

Whispering answered 6/6, 2014 at 18:37 Comment(1)
Whoa!! I have been searching for so long. Finally stumbled upon this. Thanks a lot!Marela
M
6

IMPORTANT!!:

Paul's solution is the correct answer to the question, not Dr Rob's.

Although you can just use valid() instead of validate().form().

But more importantly, there really is no reason to restrict your code as suggested by Dr Rob, ie, not .click and only use .submit. That isn't what solved the problem! What solved the problem was wrapping the $.ajax(...) call in the if statement. Ie:

if($("#MyForm").valid())
{
    //call to $.ajax or equivalent goes in here.
}

I think that needs clarifying as otherwise the real answer to the problem is obfuscated.

Morning answered 8/9, 2011 at 9:32 Comment(3)
The problem with using Click is that you still have to handle the Submit event from the form. If you make an ajax call with the click event it can get trumped by the Submit action if you don't handle that explicitly... My solution is, I'm sure, one of many, I did not vote is as being the answer other people did... As I said in my post I spent quite some time trying to make Click do things it didn't want to do, as soon as I cut over to Submit it solved "MY" problem.Cisco
Sorry to raise the dead with this post, but I want to add some input for passersby. The more obvious issue should be that you don't have to click a button to submit a form, which causes some strange behavior cross-browser. If a user hits the enter key on a form field, the browser might be nice enough to look for a submit button to fire a click event on. Otherwise, it's just going to submit the form without a click event, submit button be damned. After all, if for some reason you have multiple submit buttons... how should it know which one should be clicked on submit?Doucet
@Doucet I agree. I've all but stopped using <input type="submit" /> in any code that uses Ajax calls. I'm handling the Ajax call anyway, no need to add issues with possible submits. Just use <input type="button" /> and handle whatever actions you want.Davies
D
1

$(YourForm).data('unobtrusiveValidation').validate()

Donata answered 17/11, 2014 at 7:53 Comment(1)
Welcome on Stackoverflow, please add why this works.Adoration
S
0
        if(!$('#myform').data('unobtrusiveValidation').validate())
        {
           // add your extra custom logic
        } 
        else
        { 
             $('#myform').submit(); 
        }

It triggers the validation and returns a boolean, so you can check before submit.

Sippet answered 8/5, 2015 at 20:25 Comment(0)
T
0

.Valid() works. i.e it tells you whether your form is valid. However alone it does not help to show AND hide messages correctly. here's my manual validation method

function validate()
        {
            //valid() not only tells us whether the form is valid but 
            //also ensures that errors are shown !!!
            if ($("form").valid())
            {
                //if the form is valid we may need to hide previously displayed messages
                $(".validation-summary-errors").css("display", "none");
                $(".input-validation-error").removeClass("input-validation-error");
                return true;
            }
            else
            {
                //the form is not valide and because we are doing this all manually we also have to
                //show the validation summary manually 
                $(".validation-summary-errors").css("display", "block");
                return false;
            }
        }
Taneshatang answered 29/5, 2015 at 6:40 Comment(0)
D
0
I tried all of the above solutions but none worked on MVC5. 

I am using jQuery v2.1.4 and jQuery.Validation v1.11.1. I need to trigger validation while on page render. Only below one worked for me.

$(document).ready(function () {
   ...
   validateForm();
}

function validateForm() {`enter code here`
    var elem = document.getElementById('btnSave');
    elem.click();    
}

$('#btnSave').click(function (evt) {
    //evt.preventDefault();
    var form = $('form');
    if (form.valid()) {
        //Ajax call here
    }
    //$(".validation-summary-errors").css("display", "block");
});

function Validate() {
    // If no group name provided the whole page gets validated
    Page_ClientValidate();
}
Ditty answered 15/8, 2015 at 20:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.