ASP.NET MVC 3 Razor - Ajout d'une classe à EditorFor

189

J'essaye d'ajouter une classe à une entrée.

Cela ne fonctionne pas:

@Html.EditorFor(x => x.Created, new { @class = "date" })
user137348
la source
1
hey vous avez même le bon nom aussi! - (pour mon code)
Pincer le
1
REMARQUE: pour certaines des réponses, même si elles sont correctes, il se peut que vous deviez vider le cache du navigateur pour qu'il soit actualisé. Cela est particulièrement vrai si la solution est basée sur css ou implique une classe css! Je viens de passer un certain temps à réaliser cela avec un problème légèrement différent ....
JosephDoggie

Réponses:

183

Ajouter une classe à Html.EditorForn'a pas de sens car dans son modèle, vous pouvez avoir de nombreuses balises différentes. Vous devez donc affecter la classe dans le modèle de l'éditeur:

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

et dans le modèle personnalisé:

<div>
    @Html.TextBoxForModel(x => x.Created, new { @class = "date" })
</div>
Darin Dimitrov
la source
5
Cela fonctionne très bien, merci. J'ai des difficultés à mettre en forme la valeur du champ par l'annotation DisplayFormat dans mon modèle. Formaté comme annoté avec EditorFor et DisplayFor, mais pas TextBoxFor: (On dirait que je dois utiliser un modèle personnalisé, à moins que quelqu'un ne puisse me signaler quelque chose qui me manque.?
Sean
Avoir le même problème où TextBoxFor ne respecte pas l'ensemble DisplayFormat.
jocull
14
C'est GroundController à ModelTom, je vous envoie la vue et je flotte de la manière la plus MVC.
Trent Stewart
3
J'ai le même problème, mais je ne peux pas utiliser TextBoxFor car j'ai besoin de DisplayFormat, qui fonctionne avec Editor ou Display, mais en même temps j'ai besoin de cours aussi, afin de pouvoir afficher le texte sous forme de lecture seule
AT
153

À partir d'ASP.NET MVC 5.1, l'ajout d'une classe à un EditorForest possible (la question d'origine spécifiait ASP.NET MVC 3, et la réponse acceptée est toujours la meilleure avec celle considérée).

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

Voir: Quoi de neuf dans ASP.NET MVC 5.1, prise en charge de Bootstrap pour les modèles d'éditeur

EF0
la source
C'est génial. Merci!
Neill
1
J'ai failli manquer cela car il est 3e sur la liste. Il serait probablement utile d'en faire sa propre question et d'y répondre vous-même.
Robb Sadler
Pendant MVC 2,3,4 je n'avais pas de sens ... mais comme de plus en plus de gens ont commencé à utiliser et à se plaindre de son manque - Cela a soudainement pris du sens dans MVC 5: D +1
Piotr Kula
Cela devrait maintenant être la réponse acceptée à mon avis.
Manfred
101

Vous ne pouvez pas définir de classe pour le EditorFor générique. Si vous connaissez l'éditeur que vous voulez, vous pouvez l'utiliser tout de suite, vous pouvez y définir la classe. Vous n'avez pas besoin de créer de modèles personnalisés.

@Html.TextBoxFor(x => x.Created, new { @class = "date" }) 
TuomasK
la source
5
Bonne affaire, c'était bien de ne pas avoir besoin de créer un modèle personnalisé.
Steve Duitsman le
tu as gagné beaucoup de temps pour moi jo!
Prashanth Benny
40

Vous pouvez utiliser:

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

(Au moins avec ASP.NET MVC 5, mais je ne sais pas comment c'était avec ASP.NET MVC 3.)

przno
la source
Veuillez lire le titre de la question, c'est le problème pour MVC3, vous fournissez la solution MVC5 qui est complètement trompeuse.
Vincent
11
Et vous s'il vous plaît lire tout mon article où je l'ai écrit pour MVC5. C'était le premier résultat de Google, donc après avoir trouvé la solution que je voulais, partagez-la ici, peut-être que cela peut aider certaines personnes.
przno
Celui-ci m'a aidé! Merci @przno
Joakim M
29

J'ai eu le même problème frustrant et je ne voulais pas créer un EditorTemplate qui s'appliquait à toutes les valeurs DateTime (il y avait des moments dans mon interface utilisateur où je voulais afficher l'heure et non un calendrier déroulant de l' interface utilisateur jQuery ). Dans mes recherches, les problèmes fondamentaux que j'ai rencontrés étaient:

  • L' assistant standard TextBoxFor m'a permis d'appliquer une classe personnalisée de "date-picker" pour rendre le calendrier discret de l'interface utilisateur jQuery, mais TextBoxFor ne formaterait pas un DateTime sans l'heure, provoquant ainsi l'échec du rendu du calendrier.
  • Le EditorFor standard afficherait le DateTime sous forme de chaîne formatée (lorsqu'il est décoré avec les attributs appropriés tels que [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], mais il ne me permettrait pas d'appliquer la classe "date-picker" personnalisée.

Par conséquent, j'ai créé une classe HtmlHelper personnalisée qui présente les avantages suivants:

  • La méthode convertit automatiquement le DateTime en ShortDateString requis par le calendrier jQuery (jQuery échouera si l'heure est présente).
  • Par défaut, l'assistant appliquera les htmlAttributes requis pour afficher un calendrier jQuery, mais ils peuvent être remplacés si nécessaire.
  • Si la date est null, ASP.NET MVC mettra une date de 1/1/0001 comme valeur.

Cette méthode remplace cela par une chaîne vide.

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

Et pour ceux qui veulent connaître la syntaxe JQuery qui recherche des objets avec la date-pickerdécoration de classe pour ensuite rendre le calendrier, le voici:

$(document).ready(function () {
    $('.date-picker').datepicker({ inline: true, maxDate: 0, changeMonth: true, changeYear: true });
    $('.date-picker').datepicker('option', 'showAnim', 'slideDown');
});
bigmac
la source
Cela m'a aidé tout à l'heure, petit problème avec cela - vous devez vérifier pour vous assurer que la valeur valueAttribute.Value n'est pas vide ou un espace avant de la passer à la méthode DateTime.Parse, sinon vous risquez qu'une exception FormatException soit lancée sur un champ vide.
Moo
Merci. Vous m'avez beaucoup aidé.
Bronzato
Cela m'a aidé, mais si vous implémentez cela et que vous vous attendez à ce que le champ effectue la validation, vous devrez appliquer cette logique: stackoverflow.com/questions/12023970/…
Aaron Newton
Bon travail, mais saviez-vous que vous pouvez contrôler si un contrôle DateHeure ou juste un contrôle Date apparaît simplement en utilisant DateTimePickerForet en mettant à jour le champ de date du modèle que vous représentez avec [DataType(DataType.Date)]ou [DataType(DataType.DateTime)]? Vous pouvez également le mettre sous la forme, par exemple, mm / jj / aaaa avec .ParseFormats(new string[] { "MM/dd/yyyy" })(ou le modifier comme vous le souhaitez, facilement). S'il est nul, le champ est rendu vide sans avoir à le coder.
vapcguy
Razor ne reconnaîtra pas @MyHtmlHelpers.CalenderTextBoxFor(model => model.ExpirationDate). Des idées sur la façon de mettre en œuvre cela?
Mehdiway
15

Il est possible de fournir une classe ou d'autres informations via AdditionalViewData - J'utilise ceci lorsque j'autorise un utilisateur à créer un formulaire basé sur des champs de base de données (propertyName, editorType et editorClass).

Sur la base de votre exemple initial:

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

et dans le modèle personnalisé:

<div>
    @Html.TextBoxFor(x => x.Created, new { @class = ViewData["cssClass"] })
</div>
Brett
la source
8
@ Html.EditorFor (x => x.Created, new {cssClass = "date"}) n'a pas fonctionné pour moi
Alan Macdonald
1
Cela a fonctionné pour moi et est une meilleure réponse que celle indiquée. Il offre l'avantage d'utiliser un modèle, tout en permettant une certaine personnalisation sans hacks jQuery.
Chad Hedgcock
TextBoxFor ignore les autres attributs que l'on peut définir dans le modèle, comme 'DataType's par exemple.
Markus
8

Il n'y a aucun EditorForremplacement qui vous permet de transmettre un objet anonyme dont les propriétés seraient en quelque sorte ajoutées en tant qu'attributs sur certaines balises, en particulier pour les modèles d'éditeur intégrés. Vous devrez écrire votre propre modèle d'éditeur personnalisé et transmettre la valeur souhaitée en tant que données d'affichage supplémentaires.

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

n'autorise pas la transmission d'arguments pour la zone de texte

C'est ainsi que vous pouvez appliquer des attributs.

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

En utilisant jQuery, vous pouvez le faire facilement:

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

Voici votre balise d'entrée

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

Pour DropDownlist, vous pouvez utiliser celui-ci:

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

Pour la liste déroulante:

@Html.DropDownlistFor(model=>model.Name)
Député de Praveen
la source
2

Alors que la question visait MVC 3.0, nous constatons que le problème persiste également dans MVC 4.0. MVC 5.0 inclut désormais nativement une surcharge pour htmlAttributes.

Je suis obligé d'utiliser MVC 4.0 sur mon lieu de travail actuel et j'ai besoin d'ajouter une classe css pour l'intégration JQuery. J'ai résolu ce problème en utilisant une seule méthode d'extension ...

Méthode d'extension:

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

Utilisation du balisage HTML:

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

(Assurez-vous d'inclure l'espace de noms de la méthode d'extension dans la vue rasoir)

Explication: L'idée est d'injecter dans le HTML existant. J'ai choisi d'analyser l'élément actuel en utilisant Linq-to-XML en utilisant XDocument.Parse(). Je passe les htmlAttributes comme type object. J'utilise MVC RouteValueDictionarypour analyser les htmlAttributes transmis. Je fusionne les attributs là où ils existent déjà, ou ajoute un nouvel attribut s'il n'existe pas encore.

Dans le cas où l'entrée n'est pas analysable par, XDocument.Parse()j'abandonne tout espoir et renvoie la chaîne d'entrée d'origine.

Maintenant, je peux utiliser l'avantage de DisplayFor (rendre les types de données tels que la devise de manière appropriée) mais j'ai également la possibilité de spécifier des classes css (et tout autre attribut d'ailleurs). Cela peut être utile pour ajouter des attributs tels que data-*, ou ng-*(Angular).

barrypicker
la source
1

Vous pouvez créer le même comportement en créant un simple éditeur personnalisé appelé DateTime.cshtml, en l'enregistrant dans 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});
}

et dans vos vues

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

Notez que dans mon exemple, je codifie en dur deux classes css et le format de date. Vous pouvez bien sûr changer cela. Vous pouvez également faire la même chose avec d'autres attributs html, tels que lecture seule, désactivé, etc.

Alexandre
la source
1

J'ai utilisé une autre solution utilisant des sélecteurs d'attributs CSS pour obtenir ce dont vous avez besoin.

Indiquez l'attribut HTML que vous connaissez et mettez le style relatif que vous souhaitez.

Comme ci-dessous:

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

Pas besoin de créer un modèle personnalisé pour MVC 4. Utilisez TextBox au lieu de EditFor ici les attributs html spéciaux ne sont pas pris en charge, il est uniquement pris en charge à partir de MVC 5. TextBox doit prendre en charge MVC 4, je ne connais pas les autres versions.

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

Vous pouvez également le faire via jQuery:

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

J'avais juste besoin de définir la taille d'une zone de texte sur une page. Le codage des attributs sur le modèle et la création de modèles d'éditeur personnalisés étaient exagérés, j'ai donc juste enveloppé l'appel @ Html.EditorFor avec une balise span qui appelait une classe qui spécifie la taille de la zone de texte.

Déclaration de classe CSS:

.SpaceAvailableSearch input
{
    width:25px;
}

Afficher le code:

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

Une meilleure façon d'appliquer une classe à @Html.EditorFor()dans MVC3 RAzor est

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


<style type="text/css">

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

Cela ajoutera du style ci-dessus à votre EditorFor()

Cela fonctionne pour MVC3.

Bilal
la source