I'm having a question regaring "has-error" class and the complex object.
Basically for single simple type it works pretty well but for a complex object it doesnt.
I have following code:
My validation:
public static MvcHtmlString ValidationErrorFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string error)
{
if (HasError(htmlHelper, ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData), ExpressionHelper.GetExpressionText(expression)))
return new MvcHtmlString(error);
else
return null;
}
private static bool HasError(this HtmlHelper htmlHelper, ModelMetadata modelMetadata, string expression)
{
string modelName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expression);
FormContext formContext = htmlHelper.ViewContext.FormContext;
if (formContext == null)
return false;
if (!htmlHelper.ViewData.ModelState.ContainsKey(modelName))
return false;
ModelState modelState = htmlHelper.ViewData.ModelState[modelName];
if (modelState == null)
return false;
ModelErrorCollection modelErrors = modelState.Errors;
if (modelErrors == null)
return false;
return (modelErrors.Count > 0);
}
Javascript
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".form-group").addClass("has-error");
},
unhighlight: function (element) {
$(element).closest(".form-group").removeClass("has-error");
}
});
Here is my editortemplate:
@model DatingWebsite.Models.UserDate
<div class="form-group@(Html.ValidationErrorFor(m=>m, " has-error"))">
@Html.LabelFor(m=>m.Birthdate, new {@class="col-sm-2 control-label"})
<div class="col-sm-10">
@Html.DropDownListFor(model => model.Day, Enumerable.Range(1, 31).Select(i => new SelectListItem { Value = i.ToString(), Text = i.ToString() }), Base.Day, new {@class="form-control" })
@Html.DropDownListFor( model => model.Month, Enumerable.Range(1, 12).Select(i => new SelectListItem { Value = i.ToString(), Text = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(i)}), Base.Month, new {@class="form-control" })
@Html.DropDownListFor( model => model.Year, Enumerable.Range(DateTime.Now.AddYears(-80).Year, 80-18).Select(i => new SelectListItem { Value = i.ToString(), Text = i.ToString()}), Base.Year, new {@class="form-control" })
@Html.ValidationMessageFor(m => m.Day, null, new { @class = "help-block" })
@Html.ValidationMessageFor(m => m.Month, null, new { @class = "help-block" })
@Html.ValidationMessageFor(m => m.Year, null, new { @class = "help-block" })
</div>
</div>
And here is the model:
[Required]
public int Day { get; set; }
[Required]
public int Month { get; set; }
[Required]
public int Year { get; set; }
Now as you can see for the validation i do (m=>m) so i pass the whole object.
1) If i dont fill anything and i submit, i get all of them red, so the style is applied, and i get all error messages in red.
2) I change the first dropdown list to a value, then the color disappears, and it is not red anymore, although i still see the other 2 error messages ...
3) if i submit again like this then it will not become red again.
Note: the pictures i added are not with drop down lists, but textboxes because it has the same problem.
Anyone has an idea what is wrong with code?
Update
I've noticed that when I add value to one textbox, then the javascript calls unheighlight function and removes the has-error class, and highlight function is not called for the other 2 textboxes.
I just had the same problem and found a solution. It's not pretty, but it seems to work.
I've added the class multi-validation-group
to my form-group
divs that can contain multiple error messages and then implemented the following custom unhighlight function, which only removes the has-error
class from the form-group
div if no error label remains visible in it.
jQuery.validator.setDefaults({
errorClass: "has-error",
highlight: function(element, errorClass, validClass) {
$(element).closest(".form-group").addClass(errorClass);
},
unhighlight: function(element, errorClass, validClass) {
var group = $(element).closest(".form-group");
var removeClass = true;
if (group.hasClass("multi-validation-group")) {
removeClass = $(group).find("label.has-error:not(:hidden)").length == 0;
}
if (removeClass) {
group.removeClass(errorClass);
}
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With