ASP.NET MVC 3 Razor - Agregando clase a EditorFor


189

Estoy tratando de agregar una clase a una entrada.

Esto no está funcionando:

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

1
oye, ¡incluso tienes el nombre correcto también! - (para mi código)
Pinch

1
NOTA: Para algunas de las respuestas, incluso si son correctas, uno puede tener que borrar la memoria caché del navegador para que se actualice. ¡Esto es especialmente cierto si la solución está basada en CSS o involucra una clase CSS! Acabamos de pasar bastante tiempo darse cuenta de que con un problema ligeramente diferente ....
JosephDoggie

Respuestas:


183

Agregar una clase Html.EditorForno tiene sentido ya que dentro de su plantilla podría tener muchas etiquetas diferentes. Por lo tanto, debe asignar la clase dentro de la plantilla del editor:

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

y en la plantilla personalizada:

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

55
Esto funciona muy bien, gracias. Tengo problemas para formatear el valor del campo según la anotación DisplayFormat en mi modelo. Formateado como anotado con EditorFor y DisplayFor, pero no TextBoxFor :( Parece que debo usar una plantilla personalizada, a menos que alguien pueda señalarme algo que me falta.
Sean

Tener el mismo problema donde TextBoxFor no respeta el conjunto DisplayFormat.
Jocull

14
Este es GroundController para ModelTom, te estoy enviando la Vista y estoy flotando de la manera más MVC.
Trent Stewart

3
Tengo el mismo problema, pero no puedo usar TextBoxFor ya que necesito DisplayFormat, que funciona con Editor o Display, pero al mismo tiempo también necesito clase, para poder mostrar texto en forma de solo lectura
EN

153

A partir de ASP.NET MVC 5.1, EditorFores posible agregar una clase a una (la pregunta original especificaba ASP.NET MVC 3, y la respuesta aceptada sigue siendo la mejor con eso considerado).

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

Consulte: Novedades de ASP.NET MVC 5.1, compatibilidad con Bootstrap para plantillas de editor


Eso es genial. ¡Gracias!
Neill

1
Casi me perdí esto, ya que es el tercero en la lista. Probablemente sería útil hacer su propia pregunta y luego responderla usted mismo.
Robb Sadler

Durante MVC 2,3,4 no tenía sentido ... pero a medida que más personas comenzaron a usar y quejarse por la falta de él, de repente tuvo sentido en MVC 5: D +1
Piotr Kula

Esta debería ser la respuesta aceptada en mi opinión.
Manfred

101

No puede establecer la clase para el EditorFor genérico. Si conoce el editor que desea, puede usarlo de inmediato, allí puede configurar la clase. No necesita crear ninguna plantilla personalizada.

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

55
Buen trato, fue agradable no necesitar construir una plantilla personalizada.
Steve Duitsman

me ahorraste mucho tiempo jo!
Prashanth Benny

40

Puedes usar:

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

(Al menos con ASP.NET MVC 5, pero no sé cómo fue eso con ASP.NET MVC 3.)


Lea el título de la pregunta, este es el problema para MVC3, proporciona una solución MVC5 que es completamente engañosa.
Vincent

11
Y por favor, lea mi publicación completa donde la escribí es para MVC5. Este fue el primer resultado de Google, así que después de encontrar la solución que quería, así que compártala aquí, tal vez pueda ayudar a algunas personas.
przno

Este me ayudó! Gracias @przno
Joakim M

29

Tuve el mismo problema frustrante y no quería crear un EditorTemplate que se aplicara a todos los valores de DateTime (hubo momentos en mi interfaz de usuario en los que quería mostrar la hora y no un calendario desplegable de jQuery UI ). En mi investigación, los problemas fundamentales que encontré fueron:

  • El TextBoxFor estándar ayudante me permitió aplicar una clase personalizada de "selector de fecha" para representar el discreto calendario jQuery UI, pero TextBoxFor no formateó un DateTime sin el tiempo, por lo tanto, el renderizado del calendario falla.
  • El EditorFor estándar mostraría DateTime como una cadena formateada (cuando está decorada con los atributos adecuados, como [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], pero no me permitiría aplicar la clase personalizada "selector de fecha".

Por lo tanto, creé la clase HtmlHelper personalizada que tiene los siguientes beneficios:

  • El método convierte automáticamente DateTime en ShortDateString que necesita el calendario jQuery (jQuery fallará si la hora está presente).
  • De manera predeterminada, el asistente aplicará los atributos htmlAttributes necesarios para mostrar un calendario jQuery, pero pueden anularse si es necesario.
  • Si la fecha es nula, ASP.NET MVC pondrá una fecha de 1/1/0001 como valor.

Este método reemplaza eso con una cadena vacía.

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());
}

Y para aquellos que desean conocer la sintaxis de JQuery que busca objetos con la date-pickerdecoración de la clase para luego renderizar el calendario, aquí está:

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

Eso me ayudó en este momento, un pequeño problema con él: debe verificar para asegurarse de que valueAttribute.Value no esté vacío o espacio en blanco antes de pasarlo al método DateTime.Parse, de lo contrario corre el riesgo de que se arroje una FormatException en un campo vacío.
Moo

Gracias. Me ayudaste mucho.
Bronzato

Esto me ayudó, sin embargo, si está implementando esto y espera que el campo realice la validación, deberá aplicar esta lógica: stackoverflow.com/questions/12023970/…
Aaron Newton

Buen trabajo, pero ¿sabía que puede controlar si aparece un control DateTime o simplemente un control Date simplemente usando DateTimePickerFory actualizando el campo de fecha del modelo que está representando con [DataType(DataType.Date)]o [DataType(DataType.DateTime)]? También puede ponerlo en, digamos, mm / dd / aaaa con .ParseFormats(new string[] { "MM/dd/yyyy" })(o modificarlo a lo que desee, fácilmente). Si es nulo, el campo se
muestra

Razor no lo reconocerá @MyHtmlHelpers.CalenderTextBoxFor(model => model.ExpirationDate). ¿Alguna idea sobre cómo implementar esto?
Mehdiway

15

Es posible proporcionar una clase u otra información a través de AdditionalViewData: lo uso cuando estoy permitiendo que un usuario cree un formulario basado en campos de base de datos (propertyName, editorType y editorClass).

Según su ejemplo inicial:

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

y en la plantilla personalizada:

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

8
@ Html.EditorFor (x => x.Created, new {cssClass = "date"}) no funcionó para mí
Alan Macdonald

1
Esto funcionó para mí y es una mejor respuesta que la marcada. Proporciona el beneficio de usar una plantilla, pero permite cierta personalización sin jQuery hacks.
Chad Hedgcock

TextBoxFor ignora otros atributos que se pueden establecer en el modelo, como 'DataType's, por ejemplo.
Markus

8

No hay ninguna EditorForanulación que le permita pasar un objeto anónimo cuyas propiedades de alguna manera se agregarían como atributos en alguna etiqueta, especialmente para las plantillas de editor incorporadas. Debería escribir su propia plantilla de editor personalizada y pasar el valor que desee como datos de vista adicionales.


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

no permite que se pasen argumentos para el cuadro de texto

Así es como puedes aplicar atributos.

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

2

Usando jQuery, puedes hacerlo fácilmente:

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

Aquí está tu etiqueta de entrada

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

Para DropDownlist puedes usar este:

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

Para la lista desplegable:

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

2

Si bien la pregunta estaba dirigida a MVC 3.0, también encontramos que el problema persiste en MVC 4.0. MVC 5.0 ahora incluye de forma nativa una sobrecarga para htmlAttributes.

Me veo obligado a usar MVC 4.0 en mi lugar de empleo actual y necesitaba agregar una clase CSS para la integración de JQuery. Resolví este problema usando un único método de extensión ...

Método de extensión:

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 de marcado HTML:

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

(Asegúrese de incluir el espacio de nombres del método de extensión en la vista de la maquinilla de afeitar)

Explicación: La idea es inyectar en el HTML existente. Opté por analizar el elemento actual usando Linq-to-XML usando XDocument.Parse(). Paso los htmlAttributes como tipo object. RouteValueDictionaryUtilizo MVC para analizar los atributos html pasados. Combino los atributos donde ya existen o agrego un nuevo atributo si aún no existe.

En el caso de que la entrada no sea analizable XDocument.Parse(), abandono toda esperanza y devuelvo la cadena de entrada original.

Ahora puedo usar el beneficio de DisplayFor (renderizando tipos de datos como la moneda de manera apropiada) pero también tengo la capacidad de especificar clases css (y cualquier otro atributo para el caso). Podría ser útil para agregar atributos como data-*, o ng-*(Angular).


1

Puede crear el mismo comportamiento creando un editor personalizado simple llamado DateTime.cshtml, guardándolo en 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});
}

y en tus puntos de vista

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

Tenga en cuenta que en mi ejemplo estoy codificando dos clases de CSS y el formato de fecha. Puedes, por supuesto, cambiar eso. También puede hacer lo mismo con otros atributos html, como solo lectura, deshabilitado, etc.


1

Utilicé otra solución usando selectores de atributos CSS para obtener lo que necesita.

Indique el atributo HTML que conoce y coloque el estilo relativo que desee.

Como abajo:

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

1

No es necesario crear una plantilla personalizada para MVC 4. Use TextBox en lugar de Edit. Aquí no se admiten atributos html especiales, solo es compatible con MVC 5. TextBox debería ser compatible con MVC 4, no sé sobre otra versión.

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


0

Solo necesitaba establecer el tamaño de un cuadro de texto en una página. La codificación de atributos en el modelo y la creación de plantillas de editor personalizadas fueron excesivas, por lo que acabo de envolver la llamada @ Html.EditorFor con una etiqueta span que llamó a una clase que especifica el tamaño del cuadro de texto.

Declaración de clase CSS:

.SpaceAvailableSearch input
{
    width:25px;
}

Ver código:

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

0

Una mejor manera de aplicar la clase @Html.EditorFor()en MVC3 RAzor es

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


<style type="text/css">

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

Agregará el estilo anterior a su EditorFor()

Funciona para MVC3.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.