ASP.net MVC 3 Razor - Adicionando classe ao EditorFor


189

Estou tentando adicionar uma classe a uma entrada.

Isto não está a funcionar:

@Html.EditorFor(x => x.Created, new { @class = "date" })

1
Ei, você também acertou o nome! - (para o meu código)
Pitada

1
NOTA: Para algumas das respostas, mesmo que estejam corretas, pode ser necessário limpar o cache do navegador para que ele seja atualizado. Isto é especialmente verdade se a solução for baseada em css ou envolver uma classe css! Apenas bastante tempo percebendo que com um problema um pouco diferente ....
JosephDoggie

Respostas:


183

Adicionar uma classe a Html.EditorFornão faz sentido, pois dentro do modelo você pode ter muitas tags diferentes. Então, você precisa atribuir a classe dentro do modelo do editor:

@Html.EditorFor(x => x.Created)

e no modelo personalizado:

<div>
    @Html.TextBoxForModel(x => x.Created, new { @class = "date" })
</div>

5
Isso funciona muito bem, obrigado. Problemas para formatar o valor do campo de acordo com a anotação DisplayFormat no meu modelo. Formatada como anotado com EditorFor e DisplayFor, mas não TextBoxFor :( Parece que eu preciso usar um modelo personalizado, a menos que alguém me pode apontar para algo que eu estou ausente.?
Sean

Tendo o mesmo problema em que TextBoxFor não respeita o conjunto DisplayFormat.
Jocull

14
Este é o GroundController para o ModelTom, estou enviando a você o View e estou flutuando da maneira mais MVC.
Trent Stewart

3
eu tenho mesmo problema, mas eu não posso usar TextBoxFor como eu preciso DisplayFormat, que trabalha com o Editor ou Display, mas ao mesmo tempo de aula eu preciso também, para que eu possa exibir texto em forma readonly
AT

153

A partir do ASP.NET MVC 5.1, EditorForé possível adicionar uma classe a um (a pergunta original especificava o ASP.NET MVC 3, e a resposta aceita ainda é a melhor com o considerado).

@Html.EditorFor(x=> x.MyProperty,
    new { htmlAttributes = new { @class = "MyCssClass" } })

Consulte: O que há de novo no ASP.NET MVC 5.1, suporte ao Bootstrap para modelos de editor


Fantástico. Obrigado!
Neill

1
Eu quase perdi isso, uma vez que é o terceiro da lista. Provavelmente seria útil fazer sua própria pergunta e depois responder você mesmo.
22616 Robb Sadler #

Durante MVC 2,3,4 eu não fazia sentido ... mas como mais pessoas começaram a usar e se queixam de falta dele - De repente, feita em sentido MVC 5: D 1
Piotr Kula

Agora, essa deve ser a resposta aceita na minha opinião.
Manfred

101

Você não pode definir a classe para o EditorFor genérico. Se você conhece o editor que deseja, pode usá-lo imediatamente, e aí pode definir a classe. Você não precisa criar modelos personalizados.

@Html.TextBoxFor(x => x.Created, new { @class = "date" }) 

5
Bom negócio, foi bom não precisar criar um modelo personalizado.
Steve Duitsman

você economizou muito tempo para mim jo!
Prashanth Benny

39

Você pode usar:

@Html.EditorFor(x => x.Created, new { htmlAttributes = new { @class = "date" } })

(Pelo menos com o ASP.NET MVC 5, mas não sei como foi o ASP.NET MVC 3.)


Por favor, leia o título da pergunta, este é o problema do MVC3, você fornece a solução MVC5 que é completamente enganosa.
Vincent

10
E você pode ler meu post inteiro, onde eu escrevi, para o MVC5. Este foi o primeiro resultado do Google; portanto, depois de encontrar a solução que queria, compartilhá-la aqui, talvez ela possa ajudar algumas pessoas.
Przno 23/04

Este me ajudou! Obrigado @przno
Joakim M

29

Eu tive o mesmo problema frustrante e não queria criar um EditorTemplate que se aplicasse a todos os valores de DateTime (havia momentos na minha interface do usuário em que eu queria exibir a hora e não um calendário suspenso da jQuery UI ). Na minha pesquisa, os principais problemas que encontrei foram:

  • O auxiliar TextBoxFor padrão me permitiu aplicar uma classe personalizada de "selecionador de data" para renderizar o calendário discreto da interface do usuário do jQuery, mas o TextBoxFor não formatava um DateTime sem o tempo, causando a falha na renderização do calendário.
  • O EditorFor padrão exibia o DateTime como uma sequência de caracteres formatada (quando decorada com os atributos adequados, como [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], mas não me permitia aplicar a classe "coletor de datas" personalizada.

Portanto, criei a classe HtmlHelper personalizada que possui os seguintes benefícios:

  • O método converte automaticamente o DateTime no ShortDateString necessário ao calendário do jQuery (o jQuery falhará se houver tempo).
  • Por padrão, o auxiliar aplicará os htmlAttributes necessários para exibir um calendário jQuery, mas eles poderão ser substituídos, se necessário.
  • Se a data for nula, o ASP.NET MVC colocará uma data de 1/1/0001 como um valor.

Este método substitui isso por uma sequência vazia.

public static MvcHtmlString CalenderTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
{
    var mvcHtmlString = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression, htmlAttributes ?? new { @class = "text-box single-line date-picker" });
    var xDoc = XDocument.Parse(mvcHtmlString.ToHtmlString());
    var xElement = xDoc.Element("input");
    if (xElement != null)
    {
        var valueAttribute = xElement.Attribute("value");
        if (valueAttribute != null)
        {
            valueAttribute.Value = DateTime.Parse(valueAttribute.Value).ToShortDateString();
            if (valueAttribute.Value == "1/1/0001")
                valueAttribute.Value = string.Empty;
        }
    }
    return new MvcHtmlString(xDoc.ToString());
}

E para aqueles que desejam conhecer a sintaxe JQuery que procura objetos com a date-pickerdecoração da classe para renderizar o calendário, aqui está:

$(document).ready(function () {
    $('.date-picker').datepicker({ inline: true, maxDate: 0, changeMonth: true, changeYear: true });
    $('.date-picker').datepicker('option', 'showAnim', 'slideDown');
});

Isso me ajudou agora, pouco problema com ele - você precisa verificar se o valueAttribute.Value não está vazio ou em branco antes de passá-lo para o método DateTime.Parse, caso contrário, corre o risco de uma FormatException ser lançada em um campo vazio.
Moo

Obrigado. Você me ajudou muito.
Bronzato

Isso me ajudou, no entanto, se você está implementando isso e você está esperando o campo para executar a validação será necessário aplicar essa lógica: stackoverflow.com/questions/12023970/...
Aaron Newton

Bom trabalho, mas você sabia que pode controlar se um DateTime ou apenas um controle Date aparece apenas usando DateTimePickerFore atualizando o campo de data do modelo com o qual você está representando [DataType(DataType.Date)]ou [DataType(DataType.DateTime)]? Você também pode colocá-lo no formato mm / dd / aaaa com .ParseFormats(new string[] { "MM/dd/yyyy" })(ou modificá-lo para o que quiser, facilmente). Se for nulo, o campo não tornar tão vazio sem ter que código que no.
vapcguy

Navalha não reconhece @MyHtmlHelpers.CalenderTextBoxFor(model => model.ExpirationDate). Alguma idéia de como implementar isso?
Mehdiway

15

É possível fornecer uma classe ou outras informações através do AdditionalViewData - eu uso isso onde estou permitindo que um usuário crie um formulário com base nos campos do banco de dados (propertyName, editorType e editorClass).

Com base no seu exemplo inicial:

@Html.EditorFor(x => x.Created, new { cssClass = "date" })

e no modelo personalizado:

<div>
    @Html.TextBoxFor(x => x.Created, new { @class = ViewData["cssClass"] })
</div>

8
@ Html.EditorFor (x => x.Created, new {cssClass = "date"}) não funcionou para mim #
Alan Macdonald

1
Isso funcionou para mim e é uma resposta melhor do que a marcada. Ele oferece o benefício de usar um modelo, mas permite alguma personalização sem hacks do jQuery.
Chad Hedgcock

TextBoxFor ignora outros atributos que podem ser definidos no modelo, como 'DataType's, por exemplo.
Markus19

8

Não há nenhuma EditorForsubstituição que permita transmitir um objeto anônimo cujas propriedades seriam adicionadas de alguma forma como atributos em alguma tag, especialmente para os modelos de editor interno. Você precisaria escrever seu próprio modelo de editor personalizado e passar o valor desejado como dados de visualização adicionais.


2
@Html.EditorFor(m=>m.Created ...) 

não permite que nenhum argumento seja passado para a caixa de texto

É assim que você pode aplicar atributos.

@Html.TextBoxFor(m=>m.Created, new { @class= "date", Name ="myName", id="myId" })

2

Usando o jQuery, você pode fazer isso facilmente:

$("input").addClass("class-name")

Aqui está sua tag de entrada

@Html.EditorFor(model => model.Name)

Para o DropDownlist, você pode usar este:

$("select").addClass("class-name")

Para o Dropdownlist:

@Html.DropDownlistFor(model=>model.Name)

2

Embora a questão tenha sido direcionada ao MVC 3.0, também encontramos o problema no MVC 4.0. O MVC 5.0 agora inclui nativamente uma sobrecarga para htmlAttributes.

Sou forçado a usar o MVC 4.0 no meu local de trabalho atual e preciso adicionar uma classe css para a integração do JQuery. Resolvi esse problema usando um método de extensão única ...

Método de extensão:

using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml.Linq;

namespace MyTest.Utilities
{
    public static class MVCHelperExtensionMethods
    {
        public static MvcHtmlString AddHtmlAttributes(this MvcHtmlString input, object htmlAttributes)
        {
            // WE WANT TO INJECT INTO AN EXISTING ELEMENT.  IF THE ATTRIBUTE ALREADY EXISTS, ADD TO IT, OTHERWISE
            // CREATE THE ATTRIBUTE WITH DATA VALUES.

            // USE XML PARSER TO PARSE HTML ELEMENT
            var xdoc = XDocument.Parse(input.ToHtmlString());
            var rootElement = (from e in xdoc.Elements() select e).FirstOrDefault();

            // IF WE CANNOT PARSE THE INPUT USING XDocument THEN RETURN THE ORIGINAL UNMODIFIED.
            if (rootElement == null)
            {
                return input;
            }

            // USE RouteValueDictionary TO PARSE THE NEW HTML ATTRIBUTES
            var routeValueDictionary = new RouteValueDictionary(htmlAttributes);

            foreach (var routeValue in routeValueDictionary)
            {
                var attribute = rootElement.Attribute(routeValue.Key);

                if (attribute == null)
                {
                    attribute = new XAttribute(name: routeValue.Key, value: routeValue.Value);
                    rootElement.Add(attribute);
                }
                else
                {
                    attribute.Value = string.Format("{0} {1}", attribute.Value, routeValue.Value).Trim();
                }
            }

            var elementString = rootElement.ToString();
            var response = new MvcHtmlString(elementString);
            return response;
        }
    }
}

Uso da marcação HTML:

@Html.EditorFor(expression: x => x.MyTestProperty).AddHtmlAttributes(new { @class = "form-control" })

(Certifique-se de incluir o espaço para nome do método de extensão na exibição de navalha)

Explicação: A idéia é injetar no HTML existente. Optei por analisar o elemento atual usando o Linq para XML usando XDocument.Parse(). Eu passo o htmlAttributes como tipo object. Utilizo o MVC RouteValueDictionarypara analisar os htmlAttributes transmitidos. Mesclo os atributos onde eles já existem ou adiciono um novo atributo se ele ainda não existir.

No caso de a entrada não ser analisável, XDocument.Parse()abandono toda a esperança e retorno a string de entrada original.

Agora eu posso usar o benefício do DisplayFor (renderizar tipos de dados como moeda adequadamente), mas também tenho a capacidade de especificar classes css (e qualquer outro atributo para esse assunto). Pode ser útil para adicionar atributos como data-*, ou ng-*(Angular).


1

Você pode criar o mesmo comportamento criando um editor personalizado simples chamado DateTime.cshtml, salvando-o em Views / Shared / EditorTemplates

@model DateTime

@{
    var css = ViewData["class"] ?? "";
    @Html.TextBox("", (Model != DateTime.MinValue? Model.ToString("dd/MM/yyyy") : string.Empty), new { @class = "calendar medium " + css});
}

e na sua opinião

@Html.EditorFor(model => model.StartDate, new { @class = "required" })

Observe que no meu exemplo estou codificando duas classes de css e o formato da data. Você pode, é claro, mudar isso. Você também pode fazer o mesmo com outros atributos html, como somente leitura, desativado etc.


1

Usei outra solução usando seletores de atributos CSS para obter o que você precisa.

Indique o atributo HTML que você conhece e coloque no estilo relativo que você deseja.

Como abaixo:

input[type="date"]
{
     width: 150px;
}

1

Não é necessário criar um modelo personalizado para o MVC 4. Use o TextBox em vez de EditFor aqui os atributos especiais de html não são suportados, ele é suportado apenas pelo MVC 5. O TextBox é compatível com o MVC 4, não conheço outra versão.

@Html.TextBox("test", "", new { @id = "signupform", @class = "form-control", @role = "form",@placeholder="Name" })


0

Eu só precisava definir o tamanho de uma caixa de texto em uma página. Os atributos de codificação no modelo e a criação de modelos de editor personalizados foram um exagero, então acabei de empacotar a chamada @ Html.EditorFor com uma tag span que chamou uma classe que especifica o tamanho da caixa de texto.

Declaração de classe CSS:

.SpaceAvailableSearch input
{
    width:25px;
}

Ver código:

<span class="SpaceAvailableSearch">@Html.EditorFor(model => model.SearchForm.SpaceAvailable)</span>

0

Uma melhor maneira de aplicar classe @Html.EditorFor()no MVC3 RAzor é

@Html.EditorFor(x => x.Created)


<style type="text/css">

#Created
{
    background: #EEE linear-gradient(#EEE,#EEE);   
    border: 1px solid #adadad;
    width:90%;
    }
</style>

Ele adicionará o estilo acima ao seu EditorFor()

Funciona para MVC3.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.