ASP.NET MVC 3 Razor - Hinzufügen einer Klasse zu EditorFor

189

Ich versuche, einer Eingabe eine Klasse hinzuzufügen.

Das funktioniert nicht:

@Html.EditorFor(x => x.Created, new { @class = "date" })
user137348
quelle
1
Hey, du hast sogar den richtigen Namen! - (für meinen Code)
Pinch
1
HINWEIS: Bei einigen Antworten muss möglicherweise der Browser-Cache geleert werden, damit sie aktualisiert werden, auch wenn sie korrekt sind. Dies gilt insbesondere dann, wenn die Lösung CSS-basiert ist oder eine CSS-Klasse umfasst! Ich habe gerade eine ganze Weile damit verbracht, das mit einem etwas anderen Problem zu realisieren ...
JosephDoggie

Antworten:

183

Das Hinzufügen einer Klasse zu Html.EditorFormacht keinen Sinn, da Sie in der Vorlage viele verschiedene Tags haben können. Sie müssen die Klasse also in der Editorvorlage zuweisen:

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

und in der benutzerdefinierten Vorlage:

<div>
    @Html.TextBoxForModel(x => x.Created, new { @class = "date" })
</div>
Darin Dimitrov
quelle
5
Das funktioniert super, danke. Probleme beim Formatieren des Feldwerts gemäß der DisplayFormat-Annotation in meinem Modell. Formatiert wie mit EditorFor und DisplayFor kommentiert, aber nicht mit TextBoxFor :( Sieht so aus, als müsste ich eine benutzerdefinierte Vorlage verwenden, es sei denn, jemand kann mich auf etwas verweisen, das mir fehlt.?
Sean
Das gleiche Problem, bei dem TextBoxFor das DisplayFormat-Set nicht berücksichtigt.
Jocull
14
Dies ist GroundController für ModelTom. Ich sende Ihnen die Ansicht und schwebe auf die MVC-Weise.
Trent Stewart
3
Ich habe das gleiche Problem, aber ich kann TextBoxFor nicht verwenden, da ich DisplayFormat benötige, das mit Editor oder Display funktioniert, aber gleichzeitig brauche ich auch Klasse, damit ich Text in schreibgeschützter Form anzeigen kann
AT
153

Ab ASP.NET MVC 5.1 ist das Hinzufügen einer Klasse zu einer EditorFormöglich (die ursprüngliche Frage hat ASP.NET MVC 3 angegeben, und die akzeptierte Antwort ist mit der berücksichtigten immer noch die beste).

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

Siehe: Neue Funktionen in ASP.NET MVC 5.1, Bootstrap-Unterstützung für Editorvorlagen

EF0
quelle
Das ist großartig. Vielen Dank!
Neill
1
Ich habe das fast verpasst, da es auf Platz 3 der Liste steht. Es wäre wahrscheinlich hilfreich, eine eigene Frage zu stellen und diese dann selbst zu beantworten.
Robb Sadler
Während MVC 2,3,4 machte ich keinen Sinn ... aber als mehr Leute anfingen, es zu benutzen und sich über das Fehlen zu beschweren - machte es plötzlich Sinn in MVC 5: D +1
Piotr Kula
Dies sollte nun meiner Meinung nach die akzeptierte Antwort sein.
Manfred
101

Sie können keine Klasse für das generische EditorFor festlegen. Wenn Sie den gewünschten Editor kennen, können Sie ihn sofort verwenden und dort die Klasse festlegen. Sie müssen keine benutzerdefinierten Vorlagen erstellen.

@Html.TextBoxFor(x => x.Created, new { @class = "date" }) 
TuomasK
quelle
5
Gut, es war schön, keine benutzerdefinierte Vorlage erstellen zu müssen.
Steve Duitsman
du hast mir viel zeit gespart jo!
Prashanth Benny
39

Sie können verwenden:

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

(Zumindest mit ASP.NET MVC 5, aber ich weiß nicht, wie das mit ASP.NET MVC 3 war.)

przno
quelle
Bitte lesen Sie den Fragentitel. Dies ist das Problem für MVC3. Sie bieten eine MVC5-Lösung an, die völlig irreführend ist.
Vincent
10
Und bitte lesen Sie meinen gesamten Beitrag, in dem ich ihn geschrieben habe, für MVC5. Dies war das erste Ergebnis von Google. Nachdem ich die gewünschte Lösung gefunden hatte, teilen Sie sie hier. Vielleicht kann sie einigen Menschen helfen.
przno
Dieser hat mir geholfen! Danke @przno
Joakim M
29

Ich hatte das gleiche frustrierende Problem und wollte keine EditorTemplate erstellen, die auf alle DateTime-Werte angewendet wurde (es gab Zeiten in meiner Benutzeroberfläche, in denen ich die Uhrzeit und keinen Dropdown-Kalender für die jQuery-Benutzeroberfläche anzeigen wollte). Bei meinen Nachforschungen stieß ich auf folgende Grundprobleme:

  • Mit dem Standard- TextBoxFor- Helfer konnte ich eine benutzerdefinierte Klasse von " Datumsauswahl" anwenden, um den unauffälligen jQuery-UI-Kalender zu rendern. TextBoxFor formatierte jedoch keine DateTime ohne die Zeit, sodass das Rendern des Kalenders fehlschlug.
  • Das Standard- EditorFor zeigt die DateTime als formatierte Zeichenfolge an (wenn es mit den richtigen Attributen wie dekoriert ist [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], aber es erlaubt mir nicht, die benutzerdefinierte "Datumsauswahl" -Klasse anzuwenden.

Daher habe ich eine benutzerdefinierte HtmlHelper-Klasse erstellt, die die folgenden Vorteile bietet:

  • Die Methode konvertiert die DateTime automatisch in den ShortDateString, der vom jQuery-Kalender benötigt wird (jQuery schlägt fehl, wenn die Uhrzeit vorhanden ist).
  • Standardmäßig wendet der Helfer die erforderlichen htmlAttributes an, um einen jQuery-Kalender anzuzeigen. Sie können jedoch bei Bedarf überschrieben werden.
  • Wenn das Datum null ist, gibt ASP.NET MVC das Datum 1/1/0001 als Wert an.

Diese Methode ersetzt dies durch eine leere Zeichenfolge.

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

Und für diejenigen, die die JQuery-Syntax kennen möchten, die nach Objekten mit der date-pickerKlassendekoration sucht, um dann den Kalender zu rendern, ist dies:

$(document).ready(function () {
    $('.date-picker').datepicker({ inline: true, maxDate: 0, changeMonth: true, changeYear: true });
    $('.date-picker').datepicker('option', 'showAnim', 'slideDown');
});
Big Mac
quelle
Das hat mir gerade geholfen, kleines Problem damit - Sie müssen überprüfen, ob valueAttribute.Value nicht leer oder Leerzeichen ist, bevor Sie es an die DateTime.Parse-Methode übergeben. Andernfalls besteht die Gefahr, dass eine FormatException in ein leeres Feld geworfen wird.
Moo
Vielen Dank. Du hast mir sehr geholfen.
Bronzato
Dies hat mir geholfen, aber wenn Sie dies implementieren und erwarten, dass das Feld eine Validierung durchführt, müssen Sie diese Logik anwenden: stackoverflow.com/questions/12023970/…
Aaron Newton
Gute Arbeit, aber wussten Sie, dass Sie steuern können, ob ein DateTime- oder nur ein Date-Steuerelement angezeigt wird, indem DateTimePickerForSie das Datumsfeld des Modells verwenden und aktualisieren, das Sie mit [DataType(DataType.Date)]oder darstellen [DataType(DataType.DateTime)]? Sie können es auch beispielsweise in die Form MM / TT / JJJJ mit .ParseFormats(new string[] { "MM/dd/yyyy" })(oder ganz einfach nach Belieben ändern). Wenn es null ist, wird das Feld als leer
gerendert,
Rasiermesser erkennt nicht @MyHtmlHelpers.CalenderTextBoxFor(model => model.ExpirationDate). Irgendwelche Ideen, wie man das umsetzt?
Mehdiway
15

Es ist möglich, eine Klasse oder andere Informationen über AdditionalViewData bereitzustellen. Ich verwende diese Option, wenn ein Benutzer ein Formular basierend auf Datenbankfeldern (propertyName, editorType und editorClass) erstellen kann.

Basierend auf Ihrem ersten Beispiel:

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

und in der benutzerdefinierten Vorlage:

<div>
    @Html.TextBoxFor(x => x.Created, new { @class = ViewData["cssClass"] })
</div>
Brett
quelle
8
@ Html.EditorFor (x => x.Created, new {cssClass = "date"}) hat bei mir nicht funktioniert
Alan Macdonald
1
Dies hat bei mir funktioniert und ist eine bessere Antwort als die markierte. Es bietet den Vorteil der Verwendung einer Vorlage, ermöglicht jedoch einige Anpassungen ohne jQuery-Hacks.
Chad Hedgcock
TextBoxFor ignoriert andere Attribute, die im Modell festgelegt werden können, wie z. B. 'DataType'.
Markus
8

Es gibt keine EditorForÜberschreibung, mit der Sie ein anonymes Objekt übergeben können, dessen Eigenschaften als Attribute für ein Tag hinzugefügt werden, insbesondere für die integrierten Editorvorlagen. Sie müssten Ihre eigene benutzerdefinierte Editorvorlage schreiben und den gewünschten Wert als zusätzliche Ansichtsdaten übergeben.

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

Es können keine Argumente für das Textfeld übergeben werden

So können Sie Attribute anwenden.

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

Mit jQuery können Sie dies ganz einfach tun:

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

Hier ist Ihr Eingabe-Tag

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

Für DropDownlist können Sie Folgendes verwenden:

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

Für Dropdown-Liste:

@Html.DropDownlistFor(model=>model.Name)
Praveen MP
quelle
2

Während die Frage auf MVC 3.0 gerichtet war, stellen wir fest, dass das Problem auch in MVC 4.0 weiterhin besteht. MVC 5.0 enthält jetzt nativ eine Überladung für htmlAttributes.

Ich bin gezwungen, MVC 4.0 an meinem derzeitigen Arbeitsplatz zu verwenden, und musste eine CSS-Klasse für die JQuery-Integration hinzufügen. Ich habe dieses Problem mit einer einzigen Erweiterungsmethode gelöst ...

Verlängerungsmethode:

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

Verwendung von HTML-Markups:

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

(Stellen Sie sicher, dass der Namespace der Erweiterungsmethode in der Rasiereransicht enthalten ist.)

Erläuterung: Die Idee ist, in den vorhandenen HTML-Code einzufügen. Ich habe mich dafür entschieden, das aktuelle Element mit Linq-to-XML zu analysieren XDocument.Parse(). Ich übergebe die htmlAttributes als Typ object. Ich verwende MVC RouteValueDictionary, um die übergebenen htmlAttributes zu analysieren. Ich füge die Attribute dort zusammen, wo sie bereits vorhanden sind, oder füge ein neues Attribut hinzu, wenn es noch nicht vorhanden ist.

Für den Fall, dass die Eingabe nicht analysiert werden kann XDocument.Parse(), gebe ich alle Hoffnung auf und gebe die ursprüngliche Eingabezeichenfolge zurück.

Jetzt kann ich den Vorteil von DisplayFor nutzen (Datentypen wie Währung entsprechend rendern), aber auch CSS-Klassen (und jedes andere Attribut für diese Angelegenheit) angeben. Kann hilfreich sein, um Attribute wie data-*oder ng-*(Angular) hinzuzufügen .

Barrypicker
quelle
1

Sie können dasselbe Verhalten erstellen, indem Sie einen einfachen benutzerdefinierten Editor namens DateTime.cshtml erstellen und in Views / Shared / EditorTemplates speichern

@model DateTime

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

und in Ihren Ansichten

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

Beachten Sie, dass ich in meinem Beispiel zwei CSS-Klassen und das Datumsformat fest codiere. Das können Sie natürlich ändern. Sie können dasselbe auch mit anderen HTML-Attributen tun, z. B. schreibgeschützt, deaktiviert usw.

Alexandre
quelle
1

Ich habe eine andere Lösung mit CSS-Attributselektoren verwendet, um das zu erhalten, was Sie benötigen.

Geben Sie das HTML-Attribut an, das Sie kennen, und geben Sie den gewünschten relativen Stil ein.

Wie unten:

input[type="date"]
{
     width: 150px;
}
Max Clapton
quelle
1

Es ist nicht erforderlich, eine benutzerdefinierte Vorlage für MVC 4 zu erstellen. Verwenden Sie TextBox anstelle von EditF. Hier werden spezielle HTML-Attribute nicht unterstützt. Sie werden nur von MVC 5 unterstützt. TextBox sollte MVC 4 unterstützen. Ich kenne keine andere Version.

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

Sie können dies auch über jQuery tun:

$('#x_Created').addClass(date);
Scott R. Frost
quelle
0

Ich musste nur die Größe eines Textfelds auf einer Seite festlegen. Das Codieren von Attributen für das Modell und das Erstellen von benutzerdefinierten Editorvorlagen waren übertrieben, daher habe ich den Aufruf @ Html.EditorFor mit einem span-Tag versehen, das eine Klasse aufruft, die die Größe des Textfelds angibt.

CSS-Klassendeklaration:

.SpaceAvailableSearch input
{
    width:25px;
}

Code anzeigen:

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

Eine beste Möglichkeit, Klasse @Html.EditorFor()in MVC3 RAzor anzuwenden, ist

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


<style type="text/css">

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

Es wird Ihren obigen Stil hinzufügen EditorFor()

Es funktioniert für MVC3.

Bilal
quelle