views:

580

answers:

3

In VS2010 and ASP.NET MVC 2, it seems that client-side validation (JQuery Futures or the stock option) doesn't quite work as advertised.

I'm noticing that "tabbing off" a validated element will not invoke the client-side validation as promised. For a required field, you have to tab into the element, enter something, then remove it completely, in order to trigger the required validation. That's not really what I'm after here, and I'm hoping it's just a configuration issue on my side.

How do I get the validation effects from previous versions so that a previous value isn't necessary (without having to modify the client-side scripts if possible)?

For those that asked here is a bit of a sample of what I'm doing on the client-side.

 <div>
    <% Html.EnableClientValidation(); %>
    <% using (Html.BeginForm("Signup", "Home", new { area = "Admin" }, FormMethod.Post, new { id = "create_account_form", action = "#" })) { %>
        <fieldset>
            <div>
                <table>
                     <tr>
                        <td><label for="Email"> Email</label></td>
                        <td><%= Html.TextBoxFor(m => m.Email, new { name = "Email", @class = "textfield" }) %></td>
                        <td colspan="2"><p class="hint"><%= Html.ValidationMessageFor(m => m.Email)%></p></td>
                    </tr>
                    <tr>
                        <td><label for="Company"> Company</label></td>
                        <td><%= Html.TextBoxFor(m => m.Company, new { name = "Company", @class = "textfield" })%></td>
                        <td colspan="2"><p class="hint"><%= Html.ValidationMessageFor(m => m.Company)%></p></td>
                    </tr>
                </table>
            </div>
        </fieldset>
    <% } %>     

A: 

Do you have this <% Html.EnableClientValidation(); %> at the top of your page?

If you do and it still don't work then could you please post some code.

EDIT

Have you included;

<script type="text/javascript" src="/scripts/jquery.validate.js"></script>
<script type="text/javascript" src="/scripts/MicrosoftMvcJQueryValidation.js"></script>
griegs
Definitely calling that, if I wasn't validation wouldn't be functional. I will update my question with code. The issue lies with behavior. I have to submit the form to get validation to trigger as opposed to "tabbing off" an element.
Daniel Crenna
A: 

I totally know what you mean here, but it's actually not an issue in the VS2010, or MVC2.

MVC2 uses jquery.validate as the validation engine, and it's an external 3rd party library. In this library, if you tab away from a field, which is required, empty, and didn't have any data entered in it since the page load - it won't notify you immediately. If you have a "number" validator though, and you enter a string - it'll identify immediately.

The good thing is - when you click Submit (or just Enter on the kb) it will try to submit the form, validate all teh fields on the client side, see that some required fields haven't been filled up and will show the validation on them! So no request to the server will be sent, that's for sure!

P.S. I'm not 100% sure, but I think it might not even be jquery.validate's fault. As far as I remember, the blur js event works only if you changed the value in the field, but I might be severely mistaken here. And if that's the case - it's not the fault of the validation framework or VS at all :)

Artiom Chilaru
ASP.NET MVC 2.0 doesn't use `jQuery.validate` by default unless you tell it to do so. `jQuery.validate` supports the tabbing off feature. I am not quite sure whether the default client validation library supports such a feature though.
Darin Dimitrov
@Artiom, This is not true. By default MVC2 does NOT use jQuery.validate for its client side validation. You can choose to use the MVC Futures library that includes the ability to use jQuery.validate but the stock MVC2 client side validation does not use this.
Alastair Pitts
Thanks Artiom. While the other comments are correct that the jQuery version of validation is in Futures and not in stock MVC2, I'm getting the same behavior in both flavours. I wonder now if the behavior I want is custom and if the literature on this feature are incorrect.
Daniel Crenna
+1  A: 

I can confirm that it does work when 'tabbing off' an element, but it appears to be an issue with specific types of validation annotations.

It appears that if you have the [Required] attribute, then the validation isn't triggered if you just tab through the corresponding input.

If you have a [RegularExpression] then this is triggered when you tab out.

My suspicion is that the validation is triggered by a combination of theonechange and blur events. This would explain why the regular expression is able to be validated (as it has changed), but not the required test.

This is my view model:

    [Required(AllowEmptyStrings = false, ErrorMessage = "Please enter a first name")]
    [StringLength(50, ErrorMessage = "Maximum of 50 characters")]
    public string FirstName { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Please enter a last name")]
    [StringLength(50, ErrorMessage = "Maximum of 50 characters")]
    public string LastName { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Please enter a unique email address")]
    [CustomValidation(typeof(User), "ValidateUniqueEmailAddress")]
    [StringLength(255, ErrorMessage = "Maximum of 255 characters")]
    [RegularExpression(EmailRegEx, ErrorMessage = "Invalid email address entered")]
    public string EmailAddress { get; set; }

and the HTML code.

<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm())
   {%>
<%: Html.ValidationSummary(true) %>
<fieldset class="colLeft">
    <legend>Required Fields</legend>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.FirstName) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.FirstName) %>
        <%: Html.ValidationMessageFor(model => model.FirstName) %>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.LastName) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.LastName) %>
        <%: Html.ValidationMessageFor(model => model.LastName) %>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.EmailAddress) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.EmailAddress) %>
        <%: Html.ValidationMessageFor(model => model.EmailAddress) %>
    </div>

As you can see, nothing fancy.

In this case, when you tab through all of the inputs (first name, last name, email address), then the [Required] validation is not triggered on any of them. If you input an invalid email address then tab out, the [RegularExpression] validation is triggered.

It seems like a bug/feature of one of the validation libraries.

NOTE: I tested this in VS 2010 as I don't have access to VS 2008, but I can't see how this would be any different in the 2 versions as the code is exactly the same between them. I also used Google Chrome.

Alastair Pitts
Alastair, I think you're right. What this likely means is I'll need to add some jquery on the client-side to get the behavior I want. I'll update with an example for others when I've got it working.
Daniel Crenna