ti-enxame.com

Como personalizar o Html.ValidationMessageFor em ASP MVC

É possível personalizar o método Html.ValidationMessageFor para que ele produza HTML diferente?

Eu quero fazer algo parecido com:

<div class="field-error-box">
    <div class="top"></div>
    <div class="mid"><p>This field is required.</p></div>
</div>
21
parleer

Não tenho certeza se é possível usar paragraph em vez de span padrão, pois pode ser impossível que o plugin de validação coloque mensagens de erro. Mas para div -s, isso é fácil - você poderia escrever um ajudante html personalizado. 

Algo ao longo destas linhas ( pode precisar de mais testes/codificação ). Você precisará incluir o namespace desse método de extensão estática em sua exibição ou colocar isso em System.Web.Mvc.Html diretamente.

public static class Validator
{
    public static MvcHtmlString MyValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
    {
        TagBuilder containerDivBuilder = new TagBuilder("div");
        containerDivBuilder.AddCssClass("field-error-box");

        TagBuilder topDivBuilder = new TagBuilder("div");
        topDivBuilder.AddCssClass("top");

        TagBuilder midDivBuilder = new TagBuilder("div");
        midDivBuilder.AddCssClass("mid");
        midDivBuilder.InnerHtml = helper.ValidationMessageFor(expression).ToString();

        containerDivBuilder.InnerHtml += topDivBuilder.ToString(TagRenderMode.Normal);
        containerDivBuilder.InnerHtml += midDivBuilder.ToString(TagRenderMode.Normal);

        return MvcHtmlString.Create(containerDivBuilder.ToString(TagRenderMode.Normal));
    }
}

Como você pode ver, isso usa o método ValidationMessageFor padrão para não interferir no processamento da mensagem de erro do plugin de validação.

E você usa isso simplesmente, como auxiliar de mensagem de validação padrão

@Html.MyValidationMessageFor(model => model.SomeRequiredField)
28
archil

Eu usei de outra maneira:

    public static MvcHtmlString DivValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        return MvcHtmlString.Create(htmlHelper.ValidationMessageFor(expression).ToString().Replace("span", "div"));
    }

Dessa forma, você pode usar o caminho embutido, mas substitua o span por um div.

Se você precisar de outras sobrecargas da função, apenas duplique conforme necessário.

7
Yogev Smila

Você pode implementar seu próprio ValidationMessageFor helper para emitir sua saída desejada ou usar algum javascript para adicionar/modificar o código HTML renderizado, mas a implementação customizada de ValidationMessageFor é a abordagem mais limpa IMHO.

Para implementar seu próprio validador ValidationMessageFor, dê uma olhada nos métodos ValidationExtensions.ValidationMessageFor e ValidationMessageHelper no código fonte do ASP.NET MVC.

Dicas de Implementação  

Como GetFormContextForClientValidation é interno, você precisa contornar essa implementação duplicando a funcionalidade interna em seu código:

FormContext formContext = htmlHelper.ViewContext.ClientValidationEnabled ? htmlHelper.ViewContext.FormContext : null;

Alguns outros métodos são privados em ValidationExtensions, como GetUserErrorMessageOrDefault, você precisaria duplicar esse código também. O que você pode fazer para evitar a duplicação de código é permitir que ValidationExtentensions.ValidationMessagePara renderizar a string de mensagem de validação que é empacotada em um intervalo e depois alterar a string renderizada de acordo com seus requisitos. Lembre-se de que "null" é retornado caso nenhum erro seja encontrado e que você precisará dos atributos de dados HTML, caso tenha o JavaScript não intrusivo ativado.

Você pode baixar o código fonte da ASP.NET MVC 3 de aqui

3
saintedlama

A única necessidade de alteração da geração de tags padrão foi no meu caso, que abrange resultados de comportamento em configurações de margem anoying.

Eu resolvi isso usando 'display: block'

Talvez isso ajude algumas pessoas ..

2
Hulvej

Talvez você possa colocar esse código

string propertyName = ExpressionHelper.GetExpressionText(expression);
string name = helper.AttributeEncode(helper.ViewData.TemplateInfo.GetFullHtmlFieldName(propertyName));

if (helper.ViewData.ModelState[name] == null ||
    helper.ViewData.ModelState[name].Errors == null ||
    helper.ViewData.ModelState[name].Errors.Count == 0)
    {
        return MvcHtmlString.Empty;
    }

na parte superior da função respondida, para que o div não apareça na carga do formulário.

0
defstat