ASP.NET MVC 3 Razor – Agregar clase a EditorFor

Estoy tratando de agregar una clase a una entrada.

Esto no está funcionando:

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

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

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

y en la plantilla personalizada:

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

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

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

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

No se 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 construir ninguna plantilla personalizada.

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

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)

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

  • El ayudante estándar TextBoxFor me permitió aplicar una clase personalizada de “selector de fecha” para representar el calendario de UI discreto de jQuery, pero TextBoxFor no formateará un DateTime sin el tiempo, lo que ocasionaría un error en la representación del calendario.
  • El Editor estándar para mostrar el DateTime como una cadena formateada (cuando está decorado con los atributos adecuados, como [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")] , pero no me lo permitió para aplicar la clase personalizada de “selector de fecha”.

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

  • El método convierte automáticamente el DateTime en el ShortDateString que necesita el calendario de jQuery (jQuery fallará si el tiempo está presente).
  • De forma predeterminada, el asistente aplicará los atributos html necesarios para mostrar un calendario de jQuery, pero se pueden anular 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(this HtmlHelper htmlHelper, Expression> 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 quieran conocer la syntax de JQuery que busca objetos con la decoración de la clase de date-picker 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'); }); 

Es posible proporcionar una clase u otra información a través de AdditionalViewData. Utilizo esto para permitir que un usuario cree un formulario basado en los campos de la base de datos (propertyName, editorType y editorClass).

En base a tu ejemplo inicial:

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

y en la plantilla personalizada:

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

No hay ningún EditorFor anular 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 integradas. Debería escribir su propia plantilla de editor personalizado y pasar el valor que desee como viewdata adicional.

 @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" }) 

Usando jQuery, puedes hacerlo fácilmente:

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

Aquí está su 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) 

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. Por supuesto, puedes cambiar eso. También puede hacer lo mismo con otros atributos html, como readonly, disabled, etc.

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

No es necesario crear una plantilla personalizada para MVC 4. Utilizar TextBox en lugar de EditFor aquí no se admiten atributos html especiales, solo es compatible con MVC 5. TextBox es compatible con MVC 4, no sé sobre otra versión.

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

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 trabajo 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 de 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 máquina de afeitar)

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

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

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

También puedes hacerlo a través de jQuery:

 $('#x_Created').addClass(date); 

Solo necesitaba establecer el tamaño de un cuadro de texto en una página. Los atributos de encoding en el modelo y la creación de plantillas personalizadas de editor fueron excesivos, así que simplemente envolví 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:

 @Html.EditorFor(model => model.SearchForm.SpaceAvailable) 

Una mejor forma de aplicar clase a @Html.EditorFor() en MVC3 RAzor es

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

Se agregará el estilo anterior a su EditorFor()

Funciona para MVC3.