KenEucker
KenEucker

Reputation: 5089

MVC Ajax form with unobstructive validation errors not going away

I am having an issue where form errors are persisting on the page even after the form is valid.

I have the following setup:

_Layout.cshtml:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
</head>

<body>
    @RenderBody()
</body>
</html>

index.cshtml:

@model SimpleForm.Models.Name
@{
    ViewBag.Title = "Form";
}

<script>
    $().ready(function () {
        $("#quote_form").submit(function () {

            return true;
        });
    });
</script>
@using (Ajax.BeginForm("RunQuote", "Page", new AjaxOptions { UpdateTargetId = "quoteSummary" }, new { id = "quote_form", onreset = "return confirm('Clear all form data?')" }))
{    
    <input type="submit" value="Send" /> 
    <fieldset>
        <legend>Name </legend>
        <dl>
            <dt>First</dt>
            <dd>@Html.TextAreaFor(m => m.first, new { onblur = "$('#quote_form').submit();" })</dd>
            <dt>Last</dt>
            <dd>@Html.TextAreaFor(m => m.last, new { onblur = "$('#quote_form').submit();" })</dd>
        </dl>
    </fieldset>

    <div class="qMatrixSubText">
        @Html.ValidationSummary()
        @{
    Html.ValidateFor(m => m.first);
    Html.ValidateFor(m => m.last);
        }
    </div>                                       
    <div id="quoteSummary" class="quoteSummary">
    </div>                                       
}

FormController.cs

using System;
using System.Web.Mvc;
using SimpleForm.Models;

namespace SimpleForm.Controllers
{
    public class FormController : Controller
    {
        //
        // GET: /Form/

        public ActionResult Index()
        {
            return View();
        }

        public String RunQuote(Name quote)
        {
            return "Success!";
        }
    }
}

Name.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace SimpleForm.Models
{
    public class Name
    {
        [Required()]
        public string first { get; set; }
        public string last { get; set; }
    }
}

The form populates fine, I see the error if I don't put anything into first and the form won't submit. After populating something into first I get the ajax call and then it posts "Success" to the div.

However, this is the problem, the error "the first field is required." still remains on the page. It's as if the ajax submit form is going through before the validation gets a chance to clear the error, and then it never gets the chance.

Any way to get the validation to still remove the errors?

Upvotes: 1

Views: 2877

Answers (2)

counsellorben
counsellorben

Reputation: 10924

The form is not being validated, because your onblur event is short-circuiting the submission process in jquery-unobtrusive-ajax.js.

Instead, change your onblur event for both fields to the following:

$(this).parents('form:first').find(':submit')[0].click(); 

This will invoke the jquery.unobtrusive-ajax.js script, causing validation to occur prior to the Ajax submission to the server.

UPDATE

When I looked back at your view, I saw that you are calling @Html.ValidateFor() for your properties. This creates HTML markup outside of the div created by @Html.ValidationSummary.

Because this markup is outside of where unobtrusive validation expects it, this markup is never overwritten, and will always remain. Remove the @Html.ValidateFor() lines. If you need to have the validation messages after your initial load, call validate() on document.ready to set your validation messages.

Upvotes: 2

KenEucker
KenEucker

Reputation: 5089

Because I haven't found a proper solution to this problem, I've decided to simply target the validation-summary-errors div and add the class display:none; to the li elements. This hides the validation errors that have otherwise not cleared before submitting the form.

$('#form_errors').children('div.validation-summary-errors').children('ul').children('li').css('display','none')

There has to be a better solution, but I've tried everything and can't figure out why my attempts to force validation don't work.

Upvotes: 0

Related Questions