Last active
August 29, 2015 13:59
-
-
Save meataxe/10603564 to your computer and use it in GitHub Desktop.
Updated version of @Html.ValidationSummary to add the validation message source to the list items
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Web.Mvc; | |
// Use in views by calling `@Html.CunningValidationSummary(...)` instead of `@Html.ValidationSummary(...)` | |
// It will give an attribute of `data-valmsg-source` on each list item in the validation summary with a value of the prop the error relates to. | |
// Then you can use js to scroll to the field in question. | |
// | |
// eg. | |
// <div data-valmsg-summary="true" class="validation-summary-errors"> | |
// <ul> | |
// <li data-valmsg-source="FundingSources">The funding sources must be $100,000</li> | |
// </ul> | |
// </div> | |
// | |
// See also: https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Mvc/Html/ValidationExtensions.cs | |
public static class CunningValidationSummaryHelper | |
{ | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper) | |
{ | |
return htmlHelper.CunningValidationSummary(false); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors) | |
{ | |
return htmlHelper.CunningValidationSummary(excludePropertyErrors, null); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, string message) | |
{ | |
return htmlHelper.CunningValidationSummary(false, message, null); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors, string message) | |
{ | |
return htmlHelper.CunningValidationSummary(excludePropertyErrors, message, null); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, string message, object htmlAttributes) | |
{ | |
return htmlHelper.CunningValidationSummary(false, message, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors, string message, object htmlAttributes) | |
{ | |
return htmlHelper.CunningValidationSummary(excludePropertyErrors, message, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, string message, IDictionary<string, object> htmlAttributes) | |
{ | |
return htmlHelper.CunningValidationSummary(false, message, htmlAttributes); | |
} | |
public static MvcHtmlString CunningValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors, string message, IDictionary<string, object> htmlAttributes) | |
{ | |
if (htmlHelper == null) | |
{ | |
throw new ArgumentNullException("htmlHelper"); | |
} | |
var formContextForClientValidation = GetFormContextForClientValidation(htmlHelper.ViewContext); | |
if (htmlHelper.ViewData.ModelState.IsValid) | |
{ | |
if (formContextForClientValidation == null) | |
{ | |
return null; | |
} | |
if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled && excludePropertyErrors) | |
{ | |
return null; | |
} | |
} | |
string str; | |
if (!string.IsNullOrEmpty(message)) | |
{ | |
var tagBuilder = new TagBuilder("span"); | |
tagBuilder.SetInnerText(message); | |
str = tagBuilder.ToString(TagRenderMode.Normal) + Environment.NewLine; | |
} | |
else | |
{ | |
str = null; | |
} | |
var stringBuilder = new StringBuilder(); | |
var tagBuilder2 = new TagBuilder("ul"); | |
Dictionary<string, ModelState> enumerable = null; // This is probably a shit way to get the name | |
if (excludePropertyErrors) | |
{ | |
// Not sure if we care about adding `data-valmsg-source` in this case? | |
ModelState modelState; | |
htmlHelper.ViewData.ModelState.TryGetValue(htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix, out modelState); | |
if (modelState != null) | |
{ | |
enumerable = new Dictionary<string, ModelState> { { string.Empty, modelState } }; | |
} | |
} | |
else | |
{ | |
if (htmlHelper.ViewData.ModelState != null && htmlHelper.ViewData.ModelState.Any()) | |
{ | |
enumerable = htmlHelper.ViewData.ModelState.ToDictionary(modelState => modelState.Key, modelState => modelState.Value); | |
} | |
} | |
if (enumerable != null) | |
{ | |
// `current` is a field on the submitted form, we want to get its id or name attribute. | |
foreach (var current in enumerable) | |
{ | |
// `current2` is an error associated with a field on the form | |
foreach (var current2 in current.Value.Errors) | |
{ | |
var userErrorMessageOrDefault = GetUserErrorMessageOrDefault(current2); | |
if (!string.IsNullOrEmpty(userErrorMessageOrDefault)) | |
{ | |
var tagBuilder3 = new TagBuilder("li"); | |
var nameOrId = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(current.Key); | |
tagBuilder3.MergeAttribute("data-valmsg-source", nameOrId); | |
tagBuilder3.SetInnerText(userErrorMessageOrDefault); | |
stringBuilder.AppendLine(tagBuilder3.ToString(TagRenderMode.Normal)); | |
} | |
} | |
} | |
} | |
if (stringBuilder.Length == 0) | |
{ | |
stringBuilder.AppendLine("<li style=\"display:none\"></li>"); | |
} | |
tagBuilder2.InnerHtml = stringBuilder.ToString(); | |
var tagBuilder4 = new TagBuilder("div"); | |
tagBuilder4.MergeAttributes(htmlAttributes); | |
tagBuilder4.AddCssClass(htmlHelper.ViewData.ModelState.IsValid ? HtmlHelper.ValidationSummaryValidCssClassName : HtmlHelper.ValidationSummaryCssClassName); | |
tagBuilder4.InnerHtml = str + tagBuilder2.ToString(TagRenderMode.Normal); | |
if (formContextForClientValidation != null) | |
{ | |
if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled) | |
{ | |
if (!excludePropertyErrors) | |
{ | |
tagBuilder4.MergeAttribute("data-valmsg-summary", "true"); | |
} | |
} | |
else | |
{ | |
tagBuilder4.GenerateId("validationSummary"); | |
formContextForClientValidation.ValidationSummaryId = tagBuilder4.Attributes["id"]; | |
formContextForClientValidation.ReplaceValidationSummary = !excludePropertyErrors; | |
} | |
} | |
return new MvcHtmlString(tagBuilder4.ToString(TagRenderMode.Normal)); | |
} | |
private static FormContext GetFormContextForClientValidation(ViewContext context) | |
{ | |
return !context.ClientValidationEnabled ? null : context.FormContext; | |
} | |
private static string GetUserErrorMessageOrDefault(ModelError error) | |
{ | |
return !string.IsNullOrEmpty(error.ErrorMessage) ? error.ErrorMessage : null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment