Platypus Maximus Platypus Maximus - 4 years ago 108
C# Question

Inconsistent error message DOM betweeen jQuery validation and Postback

My error message html structure from jQuery validation and from postbacks are different causing my validation errors to display differently. I need the nested span tag within the span.field-validation-error because I use CSS to add the (x) icon before the message like the one you see on the Description error message.

This is the error message from jQuery validation.

<span class="field-validation-error" data-valmsg-for="Code" data-valmsg-replace="true">
<span id="Code-error" class="">The Description field is required.</span>

notice that on the banner url validation message, there's no span tag within the span.field-validation-error.

<span class="field-validation-error" data-valmsg-for="BannerUrl" data-valmsg-replace="true">
The Banner Image field is required.

This is the view cshtml file markup I have.

<div class="form-group">
@Html.LabelFor(x => x.Description):
@Html.TextAreaFor(x => x.Description, new { rows = 5, cols = 5, @class = "form-control", placeholder = "Enter your team description" })
@Html.ValidationMessageFor(x => x.Description)

<div class="form-group">
@Html.LabelFor(x => x.BannerUrl):
<input id="BannerUrl" name="BannerUrl" type="file" class="file-styled">
@Html.ValidationMessageFor(x => x.BannerUrl)

Why does the error message html from jquery validation different from the error message html that's generated after postback?

enter image description here


Below is the CSS that adds the (X) icon before the error message. What I really want it to do is for the icon to show up in front of the error message that comes from a postback (no nested span) and also the error message from jquery validation (nested span).

.field-validation-error > span:before {
font-family: 'icomoon';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
min-width: 1em;
display: inline-block;
text-align: center;
font-size: 16px;
vertical-align: middle;
position: relative;
top: -1px;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
content: "\ed63";
margin-right: 5px;

Answer Source

The jquery.validate.js plugin and the MVC framework are developed by separate teams (jquery.validate is not associated with Microsoft). The MVC framework just uses jquery.validate.js for client side validation (and use jquery.validate.unobtrusive.js to add the rules to jquery.validate.js).

You could create you own HtmlHelper extension to generate the inner <span> element server side. For example, copy the ValidationExtensions.cs source code and modify the private static MvcHtmlString ValidationMessageHelper(...) method so that instead of builder.SetInnerText(validationMessage); you use builder.InnerHtml = xx; where xx is a TagBuilder that builds a <span> containing the error message.

However, it would be easier to just use some javascript to wrap the inner text inside a <span> element when the page is first loaded

// Get all the elements generated by ValidationMessageFor() that have an error
var errors = $('.field-validation-error');
$.each(errors, function (index, item) {
    // Wrap the text in a span element

Note that the jquery.validate plugin also adds an id attribute to the span based on the property name. It does not appear that you need that based on your css, however, if you do want to include that, then you can use

$.each(errors, function (index, item) {
    var id = $(this).data('valmsg-for').replace(/[\.\[\]]/g, "_") + '-error';
    var span = $('<span></span>').attr('id', id);

Another option would be to wrap each ValidationMessageFor() inside an element, for example

<span class="error">

and modify the css selector

.error > .field-validation-error:before {
    font-family: 'icomoon';
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download