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" })
usuario137348
fuente
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>
Darin Dimitrov
fuente
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

EF0
fuente
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" }) 
TuomasK
fuente
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.)

przno
fuente
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');
});
bigmac
fuente
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>
Brett
fuente
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.

marcind
fuente
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" })
Jayant Varshney
fuente
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)
Praveen MP
fuente
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).

barrypicker
fuente
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.

Alexandre
fuente
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;
}
Max Clapton
fuente
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" })
Merbin Jo
fuente
0

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

$('#x_Created').addClass(date);
Scott R. Frost
fuente
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>
Conde
fuente
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.

Bilal
fuente