我有一个关于“has-error”类和复杂对象的问题。
基本上对于单个简单类型,它的效果非常好,但对于复杂的对象,它并不适用。
我有以下代码:
我的验证:
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");
}
});
这是我的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>
以下是模型:
[Required]
public int Day { get; set; }
[Required]
public int Month { get; set; }
[Required]
public int Year { get; set; }
现在你可以看到我做的验证(m =&gt; m),所以我传递了整个对象。
1)如果我没有填写任何内容并且我提交,我将所有这些都设置为红色,因此应用了样式,并且我将所有错误消息都显示为红色。
2)我将第一个下拉列表更改为一个值,然后颜色消失,它不再是红色,虽然我仍然看到其他2个错误消息......
3)如果我再次提交,那么它将不会再次变红。
注意:我添加的图片不是下拉列表,而是文本框,因为它有同样的问题。
任何人都知道代码有什么问题吗?
更新
我注意到当我向一个文本框添加值时,javascript调用unheighlight函数并删除has-error类,并且不会为其他2个文本框调用highlight函数。
答案 0 :(得分:1)
我遇到了同样的问题并找到了解决方案。它不漂亮,但似乎有效。
我已将类multi-validation-group
添加到可包含多个错误消息的form-group
div中,然后实现了以下自定义unhighlight函数,该函数仅从has-error
类中删除form-group
类{1}} div如果其中没有可见的错误标签。
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);
}
}
});
答案 1 :(得分:0)
更简洁的方法是构建HTML Bootstrap标记,以便每个输入都有自己的表单组,这样验证highlight
和unhighlight
方法就可以正常工作。 Bootstrap documentation可以向您展示如何构建适当的HTML表单布局以适应这种情况。