Difference between html rendered when client valid

2019-05-31 16:05发布

问题:

I'm creating a brand new MVC3 site. Client side validation enabled on the web.config

<appSettings>
   <add key="ClientValidationEnabled" value="true"/> 
   <add key="UnobtrusiveJavaScriptEnabled" value="true"/> 
</appSettings>

Scenario #1: Output HTML generated after a failed (client side) validation:

<span data-valmsg-replace="true" data-valmsg-for="UserName" class="field-validation-error">
    <span htmlfor="UserName" generated="true" class="">Please enter an email address</span>
</span>

Note the nested span tag where the innermost tag has a class=""

Scenario #2: Custom Server-side validation. With the same web.config configuration, I added a validation on the server to check for a custom business rule. The validation fails, I add the error to the ModelState.

The HTML generated looks like this:

<span data-valmsg-replace="true" data-valmsg-for="UserName" class="field-validation-error">Please enter a valid email address</span>

Note that just one span tag was generated, NOT a nested tag.

This behavior is making it a pain to deal with my CSS as I can't just style the .field-validation-error class as there are 2 different end results on my generated HTML.

IN SUMMARY: Client side validation generates just 1 span tag, server side validation generates 2 span tags.

QUESTION: Is this the indented behavior of the framework or am I doing something wrong?

回答1:

Is this the indented behavior of the framework or am I doing something wrong?

You are not doing anything wrong. It's just how the jquery.validate.unobtrusive.js script works. So you may call this a missing feature, discrepancy, PITA, whatever but that's how they did it out of the box.

This being said the jquery validate plugin is extensible and we can tweak it as we like:

$.validator.setDefaults({
    // customize the way errors are shown
    showErrors: function (errorMap, errorList) {
        if (errorList.length < 1) {
            // because we have customized the way errors are shown
            // we need to clean them up if there aren't any
            $('.field-validation-error', this.currentForm).hide().attr('class', 'field-validation-valid');
            $('.input-validation-error', this.currentForm).removeClass('input-validation-error');
            return;
        }
        $.each(errorList, function (index, error) {
            // simply toggle the necessary classes to the corresponding span
            // to make client validation generate the same markup as server
            // side validation
            var element = $(error.element);
            element.attr('class', 'input-validation-error');
            element.next('span').show().text(error.message).attr('class', 'field-validation-error');
        })
    }
});


回答2:

If you want to always use nested spans for your validation messages after server validation failure (for styling reasons), you can do the following:

$(document).ready(function(){
    $('.field-validation-error').each(function(){
        $(this).html($('<span>').text($(this).text()));
    });
});