ASP.NET MVC 3 Razor - Aggiunta di classe a EditorFor


189

Sto cercando di aggiungere una classe a un input.

Questo non funziona:

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

1
ehi hai anche avuto il nome giusto! - (per il mio codice)
Pizzica il

1
NOTA: per alcune delle risposte, anche se sono corrette, potrebbe essere necessario svuotare la cache del browser per attualizzarla. Ciò è particolarmente vero se la soluzione è basata su CSS o prevede una classe CSS! Ho passato un po
rendermene

Risposte:


183

L'aggiunta di una classe a Html.EditorFornon ha senso in quanto all'interno del suo modello potresti avere molti tag diversi. Quindi è necessario assegnare la classe all'interno del modello dell'editor:

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

e nel modello personalizzato:

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

5
Funziona benissimo, grazie. Ho problemi a formattare il valore del campo per l'annotazione DisplayFormat nel mio modello. Formattato come annotato con EditorFor e DisplayFor, ma non TextBoxFor :( Sembra che devo usare un modello personalizzato, a meno che qualcuno non possa indicarmi qualcosa che mi manca.
Sean,

Avere lo stesso problema in cui TextBoxFor non rispetta il set DisplayFormat.
luglio

14
Questo è GroundController per ModelTom, ti invio la vista e sto fluttuando nel modo più MVC.
Trent Stewart,

3
ho lo stesso problema, ma non riesco a utilizzare TextBoxFor perché ho bisogno di DisplayFormat, che funziona con Editor o Display, ma allo stesso tempo ho bisogno anche di classe, in modo da poter visualizzare il testo in sola lettura
AT

153

A partire da ASP.NET MVC 5.1, EditorForè possibile aggiungere una classe a una (la domanda originale specificava ASP.NET MVC 3 e la risposta accettata è ancora la migliore con quella considerata).

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

Vedere: Novità di ASP.NET MVC 5.1, Supporto Bootstrap per modelli di editor


È fantastico Grazie!
Neill

1
Ho quasi perso questo dato che è il 3 ° nella lista. Sarebbe probabilmente utile farne una domanda e quindi rispondere da soli.
Robb Sadler,

Durante MVC 2,3,4 non avevo senso ... ma quando più persone hanno iniziato a usare e lamentarsi della mancanza di esso - Improvvisamente ha avuto senso in MVC 5: D +1
Piotr Kula

Questa dovrebbe essere la risposta accettata secondo me.
Manfred,

101

Non è possibile impostare la classe per EditorFor generico. Se conosci l'editor che desideri, puoi usarlo immediatamente, lì puoi impostare la classe. Non è necessario creare modelli personalizzati.

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

5
Ottimo affare, è stato bello non aver bisogno di costruire un modello personalizzato.
Steve Duitsman,

mi hai risparmiato un sacco di tempo jo!
Prashanth Benny,

40

Puoi usare:

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

(Almeno con ASP.NET MVC 5, ma non so come fosse con ASP.NET MVC 3.)


Si prega di leggere il titolo della domanda, questo è il problema per MVC3, si fornisce la soluzione MVC5 che è completamente fuorviante.
Vincent,

11
E per favore leggi tutto il mio post in cui l'ho scritto è per MVC5. Questo è stato il primo risultato di Google, quindi dopo aver trovato la soluzione che volevo, quindi condividila qui, forse può aiutare alcune persone.
przno,

Questo mi ha aiutato! Grazie @przno
Joakim M,

29

Ho avuto lo stesso problema frustrante e non volevo creare un EditorTemplate che si applicava a tutti i valori di DateTime (c'erano volte nella mia interfaccia utente in cui volevo visualizzare l'ora e non un calendario a discesa dell'interfaccia utente di jQuery ). Nella mia ricerca, i problemi alla radice che ho riscontrato sono stati:

  • L' helper standard di TextBoxFor mi ha permesso di applicare una classe personalizzata di "selettore di date" per rendere discreto il calendario dell'interfaccia utente jQuery, ma TextBoxFor non avrebbe formattato un DateTime senza l'ora, causando quindi il fallimento del rendering del calendario.
  • EditorFor standard visualizzerebbe DateTime come una stringa formattata (se decorata con gli attributi corretti come [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], ma non mi consentirebbe di applicare la classe "data-picker" personalizzata.

Pertanto, ho creato la classe HtmlHelper personalizzata con i seguenti vantaggi:

  • Il metodo converte automaticamente DateTime in ShortDateString necessario per il calendario jQuery (jQuery fallirà se è presente l'ora).
  • Per impostazione predefinita, l'helper applica gli htmlAttributes richiesti per visualizzare un calendario jQuery, ma possono essere sostituiti se necessario.
  • Se la data è nulla, ASP.NET MVC inserirà una data di 1/1/0001 come valore.

Questo metodo sostituisce quello con una stringa vuota.

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 per coloro che vogliono conoscere la sintassi di JQuery che cerca oggetti con la date-pickerdecorazione di classe per il rendering del calendario, eccolo qui:

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

Ciò mi ha aiutato in questo momento, piccolo problema con esso - è necessario verificare per assicurarsi che valueAttribute.Value non sia vuoto o vuoto prima di passarlo al metodo DateTime.Parse, altrimenti si rischia di lanciare un FormatException su un campo vuoto.
Moo

Grazie. Mi hai aiutato molto.
Bronzato,

Questo mi ha aiutato, tuttavia se stai implementando questo e ti aspetti che il campo esegua la convalida dovrai applicare questa logica: stackoverflow.com/questions/12023970/…
Aaron Newton,

Ottimo lavoro, ma sapevi che puoi controllare se un controllo DateTime o solo Date appare solo usando DateTimePickerFore aggiornando il campo data del modello che stai rappresentando con [DataType(DataType.Date)]o [DataType(DataType.DateTime)]? Puoi anche inserirlo in, diciamo, in mm / gg / aaaa con .ParseFormats(new string[] { "MM/dd/yyyy" })(o modificarlo come preferisci, facilmente). Se è null, il campo viene visualizzato come vuoto senza che sia necessario codificarlo.
vapcguy,

Il rasoio non lo riconoscerà @MyHtmlHelpers.CalenderTextBoxFor(model => model.ExpirationDate). Qualche idea su come implementarlo?
Mehdiway,

15

È possibile fornire una classe o altre informazioni tramite AdditionalViewData: lo uso dove consento a un utente di creare un modulo basato sui campi del database (propertyName, editorType e editorClass).

Sulla base del tuo esempio iniziale:

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

e nel modello personalizzato:

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

8
@ Html.EditorFor (x => x.Created, new {cssClass = "date"}) non ha funzionato per me
Alan Macdonald

1
Questo ha funzionato per me ed è una risposta migliore di quella contrassegnata. Offre il vantaggio di utilizzare un modello, pur consentendo una certa personalizzazione senza gli hack di jQuery.
Chad Hedgcock,

TextBoxFor ignora altri attributi che è possibile impostare nel modello, ad esempio 'DataType's.
Markus,

8

Non esiste alcun EditorForoverride che ti consenta di passare un oggetto anonimo le cui proprietà sarebbero in qualche modo aggiunte come attributi su alcuni tag, specialmente per i modelli di editor integrati. Dovresti scrivere il tuo modello di editor personalizzato e passare il valore desiderato come viewdata aggiuntivo.


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

non consente il passaggio di alcun argomento per la casella di testo

Ecco come è possibile applicare gli attributi.

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

2

Usando jQuery, puoi farlo facilmente:

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

Ecco il tuo tag di input

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

Per DropDownlist puoi usare questo:

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

Per l'elenco a discesa:

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

2

Mentre la domanda era rivolta a MVC 3.0, troviamo che il problema persiste anche in MVC 4.0. MVC 5.0 ora include nativamente un sovraccarico per htmlAttributes.

Sono costretto a utilizzare MVC 4.0 nella mia attuale sede di servizio e dovevo aggiungere una classe CSS per l'integrazione di JQuery. Ho risolto questo problema utilizzando un metodo di estensione singolo ...

Metodo di estensione:

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

Utilizzo del markup HTML:

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

(Assicurati di includere lo spazio dei nomi del metodo di estensione nella vista del rasoio)

Spiegazione: L'idea è quella di iniettare nell'HTML esistente. Ho scelto di analizzare l'elemento corrente utilizzando Linq-to-XML utilizzando XDocument.Parse(). Passo il htmlAttributes come tipo object. RouteValueDictionaryUso MVC per analizzare gli htmlAttributes passati. Unisco gli attributi dove esistono già, o aggiungo un nuovo attributo se non esiste ancora.

Nel caso in cui l'input non sia analizzabile, lascio perdere XDocument.Parse()ogni speranza e restituisco la stringa di input originale.

Ora posso usare il vantaggio di DisplayFor (il rendering di tipi di dati come la valuta in modo appropriato), ma ho anche la possibilità di specificare classi css (e qualsiasi altro attributo per quella materia). Potrebbe essere utile per aggiungere attributi come data-*, o ng-*(Angolare).


1

Puoi creare lo stesso comportamento creando un semplice editor personalizzato chiamato DateTime.cshtml, salvandolo in 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 nelle tue opinioni

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

Nota che nel mio esempio sto codificando due classi css e il formato della data. Ovviamente puoi cambiarlo. Puoi anche fare lo stesso con altri attributi html, come sola lettura, disabilitato, ecc.


1

Ho usato un'altra soluzione utilizzando selettori di attributi CSS per ottenere ciò di cui hai bisogno.

Indica l'attributo HTML che conosci e metti lo stile relativo che desideri.

Come sotto:

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

1

Non c'è bisogno di creare un modello personalizzato per MVC 4. Usa TextBox invece di EditPer qui gli attributi html speciali non sono supportati, è supportato solo da MVC 5. TextBox dovrebbe supportare MVC 4, non conosco altre versioni.

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


0

Avevo solo bisogno di impostare le dimensioni di una casella di testo su una pagina. Gli attributi di codifica sul modello e la creazione di modelli di editor personalizzati sono stati eccessivi, quindi ho appena racchiuso la chiamata @ Html.EditorPer un tag span che ha chiamato una classe che specifica la dimensione della casella di testo.

Dichiarazione di classe CSS:

.SpaceAvailableSearch input
{
    width:25px;
}

Visualizza codice:

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

0

Un modo migliore per applicare la classe @Html.EditorFor()in 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>

Aggiungerà lo stile sopra al tuo EditorFor()

Funziona con MVC3.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.